@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.
Files changed (106) hide show
  1. package/package.json +32 -13
  2. package/src/index.ts +116 -0
  3. package/src/layouts/ScreenLayout/ScreenLayout.example.tsx +2 -2
  4. package/src/layouts/ScreenLayout/ScreenLayout.tsx +1 -1
  5. package/src/molecules/animation/core/AnimationCore.ts +29 -0
  6. package/src/molecules/animation/domain/entities/Animation.ts +81 -0
  7. package/src/molecules/animation/domain/entities/Fireworks.ts +44 -0
  8. package/src/molecules/animation/domain/entities/Theme.ts +76 -0
  9. package/src/molecules/animation/index.ts +146 -0
  10. package/src/molecules/animation/infrastructure/services/AnimationConfigService.ts +35 -0
  11. package/src/molecules/animation/infrastructure/services/SpringAnimationConfigService.ts +67 -0
  12. package/src/molecules/animation/infrastructure/services/TimingAnimationConfigService.ts +57 -0
  13. package/src/molecules/animation/infrastructure/services/__tests__/SpringAnimationConfigService.test.ts +114 -0
  14. package/src/molecules/animation/infrastructure/services/__tests__/TimingAnimationConfigService.test.ts +105 -0
  15. package/src/molecules/animation/presentation/components/Fireworks.tsx +126 -0
  16. package/src/molecules/animation/presentation/components/__tests__/Fireworks.test.tsx +189 -0
  17. package/src/molecules/animation/presentation/hooks/__tests__/useAnimation.integration.test.ts +216 -0
  18. package/src/molecules/animation/presentation/hooks/__tests__/useFireworks.test.ts +242 -0
  19. package/src/molecules/animation/presentation/hooks/__tests__/useGesture.test.ts +111 -0
  20. package/src/molecules/animation/presentation/hooks/__tests__/useSpringAnimation.test.ts +131 -0
  21. package/src/molecules/animation/presentation/hooks/__tests__/useTimingAnimation.test.ts +175 -0
  22. package/src/molecules/animation/presentation/hooks/__tests__/useTransformAnimation.test.ts +137 -0
  23. package/src/molecules/animation/presentation/hooks/useAnimation.ts +77 -0
  24. package/src/molecules/animation/presentation/hooks/useFireworks.ts +141 -0
  25. package/src/molecules/animation/presentation/hooks/useGesture.ts +61 -0
  26. package/src/molecules/animation/presentation/hooks/useGestureCreators.ts +163 -0
  27. package/src/molecules/animation/presentation/hooks/useGestureState.ts +53 -0
  28. package/src/molecules/animation/presentation/hooks/useIconAnimations.ts +119 -0
  29. package/src/molecules/animation/presentation/hooks/useModalAnimations.ts +124 -0
  30. package/src/molecules/animation/presentation/hooks/useReanimatedReady.ts +60 -0
  31. package/src/molecules/animation/presentation/hooks/useSpringAnimation.ts +69 -0
  32. package/src/molecules/animation/presentation/hooks/useTimingAnimation.ts +111 -0
  33. package/src/molecules/animation/presentation/hooks/useTransformAnimation.ts +57 -0
  34. package/src/molecules/animation/presentation/providers/AnimationThemeProvider.tsx +62 -0
  35. package/src/molecules/animation/presentation/providers/__tests__/AnimationThemeProvider.test.tsx +165 -0
  36. package/src/molecules/animation/types/global.d.ts +97 -0
  37. package/src/molecules/calendar/domain/entities/CalendarDay.entity.ts +115 -0
  38. package/src/molecules/calendar/domain/entities/CalendarEvent.entity.ts +202 -0
  39. package/src/molecules/calendar/domain/repositories/ICalendarRepository.ts +120 -0
  40. package/src/molecules/calendar/index.ts +98 -0
  41. package/src/molecules/calendar/infrastructure/services/CalendarEvents.ts +196 -0
  42. package/src/molecules/calendar/infrastructure/services/CalendarGeneration.ts +172 -0
  43. package/src/molecules/calendar/infrastructure/services/CalendarPermissions.ts +92 -0
  44. package/src/molecules/calendar/infrastructure/services/CalendarService.ts +161 -0
  45. package/src/molecules/calendar/infrastructure/services/CalendarSync.ts +205 -0
  46. package/src/molecules/calendar/infrastructure/storage/CalendarStore.ts +307 -0
  47. package/src/molecules/calendar/infrastructure/utils/DateUtilities.ts +128 -0
  48. package/src/molecules/calendar/presentation/components/AtomicCalendar.tsx +279 -0
  49. package/src/molecules/calendar/presentation/hooks/useCalendar.ts +356 -0
  50. package/src/molecules/celebration/domain/entities/CelebrationConfig.ts +17 -0
  51. package/src/molecules/celebration/domain/entities/FireworksConfig.ts +32 -0
  52. package/src/molecules/celebration/index.ts +93 -0
  53. package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +49 -0
  54. package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +33 -0
  55. package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +78 -0
  56. package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +90 -0
  57. package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +49 -0
  58. package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +45 -0
  59. package/src/molecules/celebration/presentation/styles/CelebrationModalStyles.ts +65 -0
  60. package/src/molecules/countdown/components/Countdown.tsx +128 -0
  61. package/src/molecules/countdown/components/CountdownHeader.tsx +84 -0
  62. package/src/molecules/countdown/components/TimeUnit.tsx +73 -0
  63. package/src/molecules/countdown/hooks/useCountdown.ts +107 -0
  64. package/src/molecules/countdown/index.ts +25 -0
  65. package/src/molecules/countdown/types/CountdownTypes.ts +31 -0
  66. package/src/molecules/countdown/utils/TimeCalculator.ts +46 -0
  67. package/src/molecules/emoji/domain/entities/Emoji.ts +129 -0
  68. package/src/molecules/emoji/index.ts +177 -0
  69. package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +102 -0
  70. package/src/molecules/emoji/presentation/hooks/useEmojiPicker.ts +171 -0
  71. package/src/molecules/index.ts +24 -0
  72. package/src/molecules/long-press-menu/domain/entities/MenuAction.ts +37 -0
  73. package/src/molecules/long-press-menu/index.ts +16 -0
  74. package/src/molecules/navigation/StackNavigator.tsx +75 -0
  75. package/src/molecules/navigation/TabsNavigator.tsx +94 -0
  76. package/src/molecules/navigation/components/FabButton.tsx +45 -0
  77. package/src/molecules/navigation/components/TabLabel.tsx +47 -0
  78. package/src/molecules/navigation/createStackNavigator.ts +20 -0
  79. package/src/molecules/navigation/createTabNavigator.ts +20 -0
  80. package/src/molecules/navigation/hooks/useTabBarStyles.ts +54 -0
  81. package/src/molecules/navigation/index.ts +37 -0
  82. package/src/molecules/navigation/types.ts +118 -0
  83. package/src/molecules/navigation/utils/AppNavigation.ts +101 -0
  84. package/src/molecules/navigation/utils/IconRenderer.ts +50 -0
  85. package/src/molecules/navigation/utils/LabelProcessor.ts +70 -0
  86. package/src/molecules/navigation/utils/NavigationCleanup.ts +62 -0
  87. package/src/molecules/navigation/utils/NavigationTheme.ts +21 -0
  88. package/src/molecules/navigation/utils/NavigationValidator.ts +61 -0
  89. package/src/molecules/navigation/utils/ScreenFactory.ts +115 -0
  90. package/src/molecules/navigation/utils/__tests__/IconRenderer.getIconName.test.ts +109 -0
  91. package/src/molecules/navigation/utils/__tests__/IconRenderer.renderIcon.test.ts +116 -0
  92. package/src/molecules/navigation/utils/__tests__/LabelProcessor.processLabel.test.ts +116 -0
  93. package/src/molecules/navigation/utils/__tests__/LabelProcessor.processTitle.test.ts +59 -0
  94. package/src/molecules/navigation/utils/__tests__/NavigationCleanup.test.ts +271 -0
  95. package/src/molecules/navigation/utils/__tests__/NavigationValidator.test.ts +252 -0
  96. package/src/molecules/swipe-actions/domain/entities/SwipeAction.ts +194 -0
  97. package/src/molecules/swipe-actions/index.ts +6 -0
  98. package/src/molecules/swipe-actions/presentation/components/SwipeActionButton.tsx +131 -0
  99. package/src/theme/hooks/useResponsiveDesignTokens.ts +1 -1
  100. package/src/utilities/clipboard/ClipboardUtils.ts +71 -0
  101. package/src/utilities/clipboard/index.ts +5 -0
  102. package/src/utilities/index.ts +6 -0
  103. package/src/utilities/sharing/domain/entities/Share.ts +210 -0
  104. package/src/utilities/sharing/index.ts +205 -0
  105. package/src/utilities/sharing/infrastructure/services/SharingService.ts +165 -0
  106. 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
+ };
@@ -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
+ }