@umituz/react-native-design-system 2.3.14 → 2.3.16

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 (93) hide show
  1. package/package.json +19 -2
  2. package/src/index.ts +105 -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/celebration/domain/entities/CelebrationConfig.ts +17 -0
  38. package/src/molecules/celebration/domain/entities/FireworksConfig.ts +32 -0
  39. package/src/molecules/celebration/index.ts +93 -0
  40. package/src/molecules/celebration/infrastructure/services/FireworksConfigService.ts +49 -0
  41. package/src/molecules/celebration/presentation/components/CelebrationFireworksOverlay.tsx +33 -0
  42. package/src/molecules/celebration/presentation/components/CelebrationModal.tsx +78 -0
  43. package/src/molecules/celebration/presentation/components/CelebrationModalContent.tsx +90 -0
  44. package/src/molecules/celebration/presentation/hooks/useCelebrationModalAnimation.ts +49 -0
  45. package/src/molecules/celebration/presentation/hooks/useCelebrationState.ts +45 -0
  46. package/src/molecules/celebration/presentation/styles/CelebrationModalStyles.ts +65 -0
  47. package/src/molecules/countdown/components/Countdown.tsx +128 -0
  48. package/src/molecules/countdown/components/CountdownHeader.tsx +84 -0
  49. package/src/molecules/countdown/components/TimeUnit.tsx +73 -0
  50. package/src/molecules/countdown/hooks/useCountdown.ts +107 -0
  51. package/src/molecules/countdown/index.ts +25 -0
  52. package/src/molecules/countdown/types/CountdownTypes.ts +31 -0
  53. package/src/molecules/countdown/utils/TimeCalculator.ts +46 -0
  54. package/src/molecules/emoji/domain/entities/Emoji.ts +129 -0
  55. package/src/molecules/emoji/index.ts +177 -0
  56. package/src/molecules/emoji/presentation/components/EmojiPicker.tsx +102 -0
  57. package/src/molecules/emoji/presentation/hooks/useEmojiPicker.ts +171 -0
  58. package/src/molecules/index.ts +21 -0
  59. package/src/molecules/long-press-menu/domain/entities/MenuAction.ts +37 -0
  60. package/src/molecules/long-press-menu/index.ts +16 -0
  61. package/src/molecules/navigation/StackNavigator.tsx +75 -0
  62. package/src/molecules/navigation/TabsNavigator.tsx +94 -0
  63. package/src/molecules/navigation/components/FabButton.tsx +45 -0
  64. package/src/molecules/navigation/components/TabLabel.tsx +47 -0
  65. package/src/molecules/navigation/createStackNavigator.ts +20 -0
  66. package/src/molecules/navigation/createTabNavigator.ts +20 -0
  67. package/src/molecules/navigation/hooks/useTabBarStyles.ts +54 -0
  68. package/src/molecules/navigation/index.ts +37 -0
  69. package/src/molecules/navigation/types.ts +118 -0
  70. package/src/molecules/navigation/utils/AppNavigation.ts +101 -0
  71. package/src/molecules/navigation/utils/IconRenderer.ts +50 -0
  72. package/src/molecules/navigation/utils/LabelProcessor.ts +70 -0
  73. package/src/molecules/navigation/utils/NavigationCleanup.ts +62 -0
  74. package/src/molecules/navigation/utils/NavigationTheme.ts +21 -0
  75. package/src/molecules/navigation/utils/NavigationValidator.ts +61 -0
  76. package/src/molecules/navigation/utils/ScreenFactory.ts +115 -0
  77. package/src/molecules/navigation/utils/__tests__/IconRenderer.getIconName.test.ts +109 -0
  78. package/src/molecules/navigation/utils/__tests__/IconRenderer.renderIcon.test.ts +116 -0
  79. package/src/molecules/navigation/utils/__tests__/LabelProcessor.processLabel.test.ts +116 -0
  80. package/src/molecules/navigation/utils/__tests__/LabelProcessor.processTitle.test.ts +59 -0
  81. package/src/molecules/navigation/utils/__tests__/NavigationCleanup.test.ts +271 -0
  82. package/src/molecules/navigation/utils/__tests__/NavigationValidator.test.ts +252 -0
  83. package/src/molecules/swipe-actions/domain/entities/SwipeAction.ts +194 -0
  84. package/src/molecules/swipe-actions/index.ts +6 -0
  85. package/src/molecules/swipe-actions/presentation/components/SwipeActionButton.tsx +131 -0
  86. package/src/theme/hooks/useResponsiveDesignTokens.ts +1 -1
  87. package/src/utilities/clipboard/ClipboardUtils.ts +71 -0
  88. package/src/utilities/clipboard/index.ts +5 -0
  89. package/src/utilities/index.ts +6 -0
  90. package/src/utilities/sharing/domain/entities/Share.ts +210 -0
  91. package/src/utilities/sharing/index.ts +205 -0
  92. package/src/utilities/sharing/infrastructure/services/SharingService.ts +165 -0
  93. package/src/utilities/sharing/presentation/hooks/useSharing.ts +154 -0
@@ -0,0 +1,46 @@
1
+ import type { TimeRemaining } from '../types/CountdownTypes';
2
+
3
+ export function calculateTimeRemaining(targetDate: Date | string): TimeRemaining {
4
+ const now = new Date().getTime();
5
+ const target = typeof targetDate === 'string'
6
+ ? new Date(targetDate).getTime()
7
+ : targetDate.getTime();
8
+
9
+ const difference = Math.max(0, target - now);
10
+ const totalSeconds = Math.floor(difference / 1000);
11
+
12
+ const days = Math.floor(totalSeconds / (24 * 3600));
13
+ const hours = Math.floor((totalSeconds % (24 * 3600)) / 3600);
14
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
15
+ const seconds = totalSeconds % 60;
16
+
17
+ return {
18
+ days,
19
+ hours,
20
+ minutes,
21
+ seconds,
22
+ totalSeconds,
23
+ isExpired: totalSeconds <= 0,
24
+ };
25
+ }
26
+
27
+ export function padNumber(num: number): string {
28
+ return String(num).padStart(2, '0');
29
+ }
30
+
31
+ export function getNextDayStart(date?: Date): Date {
32
+ const baseDate = date || new Date();
33
+ const nextDay = new Date(baseDate);
34
+ nextDay.setDate(nextDay.getDate() + 1);
35
+ nextDay.setHours(0, 0, 0, 0);
36
+ return nextDay;
37
+ }
38
+
39
+ export function getNextYearStart(date?: Date): Date {
40
+ const baseDate = date || new Date();
41
+ const nextYear = new Date(baseDate);
42
+ nextYear.setFullYear(nextYear.getFullYear() + 1);
43
+ nextYear.setMonth(0, 1);
44
+ nextYear.setHours(0, 0, 0, 0);
45
+ return nextYear;
46
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Emoji Domain Entities
3
+ *
4
+ * Core emoji types and interfaces for emoji picker functionality
5
+ *
6
+ * Features:
7
+ * - Emoji selection with picker UI
8
+ * - Emoji object with metadata (emoji string, name, slug, unicode)
9
+ * - Category-based organization
10
+ * - Search functionality
11
+ * - Recent emojis tracking
12
+ *
13
+ * Dependencies:
14
+ * - rn-emoji-keyboard (emoji picker UI library)
15
+ */
16
+
17
+ /**
18
+ * Emoji object returned by the picker
19
+ * Conforms to rn-emoji-keyboard EmojiType structure
20
+ */
21
+ export interface EmojiObject {
22
+ /** The actual emoji character (e.g., "😀") */
23
+ emoji: string;
24
+
25
+ /** Human-readable name (e.g., "Grinning Face") */
26
+ name: string;
27
+
28
+ /** URL-friendly slug (e.g., "grinning_face") */
29
+ slug: string;
30
+
31
+ /** Unicode codepoint (e.g., "1F600") */
32
+ unicode_version: string;
33
+
34
+ /** Emoji category (e.g., "smileys_emotion") */
35
+ category?: string;
36
+ }
37
+
38
+ /**
39
+ * Emoji picker configuration
40
+ */
41
+ export interface EmojiPickerConfig {
42
+ /** Whether to show category tabs */
43
+ enableCategoryTabs?: boolean;
44
+
45
+ /** Whether to enable search */
46
+ enableSearch?: boolean;
47
+
48
+ /** Whether to show recently used emojis */
49
+ enableRecentlyUsed?: boolean;
50
+
51
+ /** Custom category order */
52
+ categoryOrder?: string[];
53
+
54
+ /** Translation object for labels */
55
+ translation?: {
56
+ search: string;
57
+ categories: Record<string, string>;
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Emoji selection callback type
63
+ */
64
+ export type EmojiSelectCallback = (emojiObject: EmojiObject) => void;
65
+
66
+ /**
67
+ * Emoji picker categories
68
+ * Based on Unicode emoji categories
69
+ */
70
+ export enum EmojiCategory {
71
+ SMILEYS_EMOTION = 'smileys_emotion',
72
+ PEOPLE_BODY = 'people_body',
73
+ ANIMALS_NATURE = 'animals_nature',
74
+ FOOD_DRINK = 'food_drink',
75
+ TRAVEL_PLACES = 'travel_places',
76
+ ACTIVITIES = 'activities',
77
+ OBJECTS = 'objects',
78
+ SYMBOLS = 'symbols',
79
+ FLAGS = 'flags',
80
+ }
81
+
82
+ /**
83
+ * Emoji picker state
84
+ */
85
+ export interface EmojiPickerState {
86
+ /** Whether picker is currently open */
87
+ isOpen: boolean;
88
+
89
+ /** Currently selected emoji (null if none selected) */
90
+ selectedEmoji: string | null;
91
+ }
92
+
93
+ /**
94
+ * Emoji validation utilities
95
+ */
96
+ export const EmojiUtils = {
97
+ /**
98
+ * Check if a string contains valid emoji
99
+ * @param text - Text to validate
100
+ * @returns True if contains emoji
101
+ */
102
+ isEmoji: (text: string): boolean => {
103
+ if (!text || text.length === 0) {
104
+ return false;
105
+ }
106
+ // Basic emoji regex (covers most common emojis)
107
+ const emojiRegex = /[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u;
108
+ return emojiRegex.test(text);
109
+ },
110
+
111
+ /**
112
+ * Extract first emoji from text
113
+ * @param text - Text containing emoji
114
+ * @returns First emoji or empty string
115
+ */
116
+ extractFirstEmoji: (text: string): string => {
117
+ const match = text.match(/[\u{1F600}-\u{1F64F}]|[\u{1F300}-\u{1F5FF}]|[\u{1F680}-\u{1F6FF}]|[\u{1F1E0}-\u{1F1FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]/u);
118
+ return match ? match[0] : '';
119
+ },
120
+
121
+ /**
122
+ * Get emoji length (handles multi-byte emojis correctly)
123
+ * @param emoji - Emoji string
124
+ * @returns Actual character count
125
+ */
126
+ getEmojiLength: (emoji: string): number => {
127
+ return Array.from(emoji).length;
128
+ },
129
+ } as const;
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Emoji Domain - Barrel Export
3
+ *
4
+ * Global infrastructure domain for emoji selection and display
5
+ *
6
+ * Features:
7
+ * - Universal emoji picker component
8
+ * - Category-based emoji selection (smileys, animals, food, etc.)
9
+ * - Search functionality
10
+ * - Recently used emojis tracking
11
+ * - React hook for state management
12
+ * - Theme-aware styling
13
+ * - Validation utilities
14
+ *
15
+ * Dependencies:
16
+ * - rn-emoji-keyboard (emoji picker UI library)
17
+ *
18
+ * USAGE:
19
+ * ```typescript
20
+ * // Method 1: Using hook (recommended)
21
+ * import { useEmojiPicker, EmojiPicker } from '@umituz/react-native-emoji';
22
+ *
23
+ * const MyComponent = () => {
24
+ * const {
25
+ * isOpen,
26
+ * selectedEmoji,
27
+ * openPicker,
28
+ * closePicker,
29
+ * handleEmojiSelect,
30
+ * } = useEmojiPicker();
31
+ *
32
+ * return (
33
+ * <View>
34
+ * <TouchableOpacity onPress={openPicker}>
35
+ * <Text style={{ fontSize: 32 }}>
36
+ * {selectedEmoji || 'Select Emoji'}
37
+ * </Text>
38
+ * </TouchableOpacity>
39
+ *
40
+ * <EmojiPicker
41
+ * open={isOpen}
42
+ * onClose={closePicker}
43
+ * onEmojiSelected={handleEmojiSelect}
44
+ * />
45
+ * </View>
46
+ * );
47
+ * };
48
+ *
49
+ * // Method 2: Manual state management
50
+ * import { EmojiPicker, type EmojiObject } from '@umituz/react-native-emoji';
51
+ *
52
+ * const MyComponent = () => {
53
+ * const [isOpen, setIsOpen] = useState(false);
54
+ * const [emoji, setEmoji] = useState('');
55
+ *
56
+ * const handleSelect = (emojiObject: EmojiObject) => {
57
+ * setEmoji(emojiObject.emoji);
58
+ * setIsOpen(false);
59
+ * };
60
+ *
61
+ * return (
62
+ * <View>
63
+ * <TouchableOpacity onPress={() => setIsOpen(true)}>
64
+ * <Text>{emoji || 'Select'}</Text>
65
+ * </TouchableOpacity>
66
+ *
67
+ * <EmojiPicker
68
+ * open={isOpen}
69
+ * onClose={() => setIsOpen(false)}
70
+ * onEmojiSelected={handleSelect}
71
+ * />
72
+ * </View>
73
+ * );
74
+ * };
75
+ *
76
+ * // Validation utilities
77
+ * import { EmojiUtils } from '@umituz/react-native-emoji';
78
+ *
79
+ * const isValid = EmojiUtils.isEmoji('😀'); // true
80
+ * const first = EmojiUtils.extractFirstEmoji('Hello 😀 World 🌍'); // '😀'
81
+ * const length = EmojiUtils.getEmojiLength('👨‍👩‍👧‍👦'); // 1 (handles multi-byte)
82
+ * ```
83
+ *
84
+ * REAL-WORLD EXAMPLE (Category Creation):
85
+ * ```typescript
86
+ * import { useEmojiPicker, EmojiPicker } from '@umituz/react-native-emoji';
87
+ * import { AtomicInput, AtomicText } from '@umituz/react-native-design-system';
88
+ *
89
+ * const AddCategoryScreen = () => {
90
+ * const [name, setName] = useState('');
91
+ * const {
92
+ * selectedEmoji,
93
+ * isOpen,
94
+ * openPicker,
95
+ * closePicker,
96
+ * handleEmojiSelect,
97
+ * } = useEmojiPicker();
98
+ *
99
+ * const handleSubmit = () => {
100
+ * if (!name.trim() || !selectedEmoji) {
101
+ * alert('Please fill all fields');
102
+ * return;
103
+ * }
104
+ *
105
+ * // Save category with emoji
106
+ * saveCategory({ name, emoji: selectedEmoji });
107
+ * };
108
+ *
109
+ * return (
110
+ * <View>
111
+ * <AtomicInput
112
+ * label="Category Name"
113
+ * value={name}
114
+ * onChangeText={setName}
115
+ * />
116
+ *
117
+ * <TouchableOpacity onPress={openPicker}>
118
+ * <Text style={{ fontSize: 32, textAlign: 'center' }}>
119
+ * {selectedEmoji || 'Tap to select emoji'}
120
+ * </Text>
121
+ * </TouchableOpacity>
122
+ *
123
+ * <AtomicButton onPress={handleSubmit}>
124
+ * Create Category
125
+ * </AtomicButton>
126
+ *
127
+ * <EmojiPicker
128
+ * open={isOpen}
129
+ * onClose={closePicker}
130
+ * onEmojiSelected={handleEmojiSelect}
131
+ * />
132
+ * </View>
133
+ * );
134
+ * };
135
+ * ```
136
+ *
137
+ * EMOJI CATEGORIES:
138
+ * - 😀 Smileys & Emotion
139
+ * - 👨 People & Body
140
+ * - 🐶 Animals & Nature
141
+ * - 🍔 Food & Drink
142
+ * - ✈️ Travel & Places
143
+ * - ⚽ Activities
144
+ * - 💡 Objects
145
+ * - ❤️ Symbols
146
+ * - 🏁 Flags
147
+ *
148
+ * FEATURES:
149
+ * - 3600+ emojis across 9 categories
150
+ * - Full Unicode 15.0 support
151
+ * - Search by name or keywords
152
+ * - Recently used tracking (persisted)
153
+ * - Category change animations
154
+ * - Smooth scrolling and gestures
155
+ * - Theme-aware (light/dark mode)
156
+ * - Localization support
157
+ */
158
+
159
+ // Domain Entities
160
+ export type {
161
+ EmojiObject,
162
+ EmojiPickerConfig,
163
+ EmojiSelectCallback,
164
+ EmojiPickerState,
165
+ } from './domain/entities/Emoji';
166
+ export { EmojiCategory, EmojiUtils } from './domain/entities/Emoji';
167
+
168
+ // Presentation Components
169
+ export { EmojiPicker } from './presentation/components/EmojiPicker';
170
+ export type { EmojiPickerProps } from './presentation/components/EmojiPicker';
171
+
172
+ // Presentation Hooks
173
+ export { useEmojiPicker } from './presentation/hooks/useEmojiPicker';
174
+ export type {
175
+ UseEmojiPickerOptions,
176
+ UseEmojiPickerReturn,
177
+ } from './presentation/hooks/useEmojiPicker';
@@ -0,0 +1,102 @@
1
+ /**
2
+ * EmojiPicker Component
3
+ *
4
+ * Universal emoji picker component wrapping rn-emoji-keyboard
5
+ * Provides a clean, factory-standard interface for emoji selection
6
+ *
7
+ * Features:
8
+ * - Category-based emoji selection
9
+ * - Search functionality
10
+ * - Recently used emojis
11
+ * - Theme-aware styling
12
+ * - Localization support
13
+ *
14
+ * Dependencies:
15
+ * - rn-emoji-keyboard (emoji picker UI library)
16
+ *
17
+ * USAGE:
18
+ * ```typescript
19
+ * import { EmojiPicker } from '@umituz/react-native-emoji';
20
+ *
21
+ * const MyComponent = () => {
22
+ * const [isOpen, setIsOpen] = useState(false);
23
+ * const [emoji, setEmoji] = useState('');
24
+ *
25
+ * const handleEmojiSelect = (emojiObject: EmojiObject) => {
26
+ * setEmoji(emojiObject.emoji);
27
+ * setIsOpen(false);
28
+ * };
29
+ *
30
+ * return (
31
+ * <>
32
+ * <TouchableOpacity onPress={() => setIsOpen(true)}>
33
+ * <Text>{emoji || 'Select Emoji'}</Text>
34
+ * </TouchableOpacity>
35
+ *
36
+ * <EmojiPicker
37
+ * open={isOpen}
38
+ * onClose={() => setIsOpen(false)}
39
+ * onEmojiSelected={handleEmojiSelect}
40
+ * />
41
+ * </>
42
+ * );
43
+ * };
44
+ * ```
45
+ */
46
+
47
+ import React from 'react';
48
+ import RNEmojiKeyboard, { EmojiType } from 'rn-emoji-keyboard';
49
+ import type { EmojiObject, EmojiPickerConfig } from '../../domain/entities/Emoji';
50
+
51
+ export interface EmojiPickerProps {
52
+ /** Whether the picker is currently open */
53
+ open: boolean;
54
+
55
+ /** Callback when picker is closed */
56
+ onClose: () => void;
57
+
58
+ /** Callback when an emoji is selected */
59
+ onEmojiSelected: (emojiObject: EmojiObject) => void;
60
+
61
+ /** Optional configuration */
62
+ config?: EmojiPickerConfig;
63
+ }
64
+
65
+ /**
66
+ * Universal emoji picker component
67
+ * Wraps rn-emoji-keyboard with factory-standard interface
68
+ */
69
+ export const EmojiPicker: React.FC<EmojiPickerProps> = ({
70
+ open,
71
+ onClose,
72
+ onEmojiSelected,
73
+ config,
74
+ }) => {
75
+ const handleEmojiSelect = (emojiObject: EmojiType) => {
76
+ // Map rn-emoji-keyboard EmojiType to our EmojiObject interface
77
+ const mappedEmoji: EmojiObject = {
78
+ emoji: emojiObject.emoji,
79
+ name: emojiObject.name,
80
+ slug: emojiObject.slug,
81
+ unicode_version: emojiObject.unicode_version,
82
+ };
83
+
84
+ onEmojiSelected(mappedEmoji);
85
+ };
86
+
87
+ return (
88
+ <RNEmojiKeyboard
89
+ onEmojiSelected={handleEmojiSelect}
90
+ open={open}
91
+ onClose={onClose}
92
+ enableCategoryChangeAnimation={true}
93
+ enableSearchAnimation={true}
94
+ categoryPosition="top"
95
+ enableRecentlyUsed={config?.enableRecentlyUsed ?? true}
96
+ enableSearchBar={config?.enableSearch ?? true}
97
+ enableCategoryChangeGesture={config?.enableCategoryTabs ?? true}
98
+ categoryOrder={config?.categoryOrder as any}
99
+ translation={config?.translation as any}
100
+ />
101
+ );
102
+ };
@@ -0,0 +1,171 @@
1
+ /**
2
+ * useEmojiPicker Hook
3
+ *
4
+ * React hook for emoji picker state management
5
+ * Provides a clean, declarative API for emoji selection
6
+ *
7
+ * Features:
8
+ * - Open/close state management
9
+ * - Selected emoji tracking
10
+ * - Clear/reset functionality
11
+ * - Simple, reusable hook pattern
12
+ *
13
+ * USAGE:
14
+ * ```typescript
15
+ * import { useEmojiPicker, EmojiPicker } from '@umituz/react-native-emoji';
16
+ *
17
+ * const MyComponent = () => {
18
+ * const {
19
+ * isOpen,
20
+ * selectedEmoji,
21
+ * openPicker,
22
+ * closePicker,
23
+ * handleEmojiSelect,
24
+ * clearEmoji,
25
+ * } = useEmojiPicker();
26
+ *
27
+ * return (
28
+ * <View>
29
+ * <TouchableOpacity onPress={openPicker}>
30
+ * <Text>{selectedEmoji || 'Select Emoji'}</Text>
31
+ * </TouchableOpacity>
32
+ *
33
+ * <EmojiPicker
34
+ * open={isOpen}
35
+ * onClose={closePicker}
36
+ * onEmojiSelected={handleEmojiSelect}
37
+ * />
38
+ * </View>
39
+ * );
40
+ * };
41
+ * ```
42
+ */
43
+
44
+ import { useState, useCallback } from 'react';
45
+ import type { EmojiObject } from '../../domain/entities/Emoji';
46
+
47
+ export interface UseEmojiPickerOptions {
48
+ /** Initial emoji value */
49
+ initialEmoji?: string;
50
+
51
+ /** Callback when emoji is selected */
52
+ onEmojiChange?: (emoji: string) => void;
53
+
54
+ /** Whether to auto-close picker after selection */
55
+ autoClose?: boolean;
56
+ }
57
+
58
+ export interface UseEmojiPickerReturn {
59
+ /** Whether the picker is currently open */
60
+ isOpen: boolean;
61
+
62
+ /** Currently selected emoji (null if none) */
63
+ selectedEmoji: string | null;
64
+
65
+ /** Open the emoji picker */
66
+ openPicker: () => void;
67
+
68
+ /** Close the emoji picker */
69
+ closePicker: () => void;
70
+
71
+ /** Toggle picker open/closed */
72
+ togglePicker: () => void;
73
+
74
+ /** Handle emoji selection (use as onEmojiSelected callback) */
75
+ handleEmojiSelect: (emojiObject: EmojiObject) => void;
76
+
77
+ /** Clear the currently selected emoji */
78
+ clearEmoji: () => void;
79
+
80
+ /** Set emoji directly (without opening picker) */
81
+ setEmoji: (emoji: string) => void;
82
+ }
83
+
84
+ /**
85
+ * Hook for emoji picker state management
86
+ */
87
+ export const useEmojiPicker = (
88
+ options?: UseEmojiPickerOptions
89
+ ): UseEmojiPickerReturn => {
90
+ const { initialEmoji, onEmojiChange, autoClose = true } = options || {};
91
+
92
+ const [isOpen, setIsOpen] = useState(false);
93
+ const [selectedEmoji, setSelectedEmoji] = useState<string | null>(
94
+ initialEmoji || null
95
+ );
96
+
97
+ /**
98
+ * Open the emoji picker
99
+ */
100
+ const openPicker = useCallback(() => {
101
+ setIsOpen(true);
102
+ }, []);
103
+
104
+ /**
105
+ * Close the emoji picker
106
+ */
107
+ const closePicker = useCallback(() => {
108
+ setIsOpen(false);
109
+ }, []);
110
+
111
+ /**
112
+ * Toggle picker open/closed
113
+ */
114
+ const togglePicker = useCallback(() => {
115
+ setIsOpen((prev) => !prev);
116
+ }, []);
117
+
118
+ /**
119
+ * Handle emoji selection
120
+ */
121
+ const handleEmojiSelect = useCallback(
122
+ (emojiObject: EmojiObject) => {
123
+ setSelectedEmoji(emojiObject.emoji);
124
+
125
+ // Call onChange callback if provided
126
+ if (onEmojiChange) {
127
+ onEmojiChange(emojiObject.emoji);
128
+ }
129
+
130
+ // Auto-close picker if enabled
131
+ if (autoClose) {
132
+ setIsOpen(false);
133
+ }
134
+ },
135
+ [onEmojiChange, autoClose]
136
+ );
137
+
138
+ /**
139
+ * Clear the currently selected emoji
140
+ */
141
+ const clearEmoji = useCallback(() => {
142
+ setSelectedEmoji(null);
143
+ if (onEmojiChange) {
144
+ onEmojiChange('');
145
+ }
146
+ }, [onEmojiChange]);
147
+
148
+ /**
149
+ * Set emoji directly
150
+ */
151
+ const setEmoji = useCallback(
152
+ (emoji: string) => {
153
+ setSelectedEmoji(emoji);
154
+ if (onEmojiChange) {
155
+ onEmojiChange(emoji);
156
+ }
157
+ },
158
+ [onEmojiChange]
159
+ );
160
+
161
+ return {
162
+ isOpen,
163
+ selectedEmoji,
164
+ openPicker,
165
+ closePicker,
166
+ togglePicker,
167
+ handleEmojiSelect,
168
+ clearEmoji,
169
+ setEmoji,
170
+ };
171
+ };
@@ -32,3 +32,24 @@ export * from './alerts';
32
32
 
33
33
  // Calendar
34
34
  export * from './calendar';
35
+
36
+ // Swipe Actions
37
+ export * from './swipe-actions';
38
+
39
+ // Navigation
40
+ export * from './navigation';
41
+
42
+ // Celebration
43
+ export * from './celebration';
44
+
45
+ // Animation
46
+ export * from './animation';
47
+
48
+ // Long Press Menu
49
+ export * from './long-press-menu';
50
+
51
+ // Emoji
52
+ export * from './emoji';
53
+
54
+ // Countdown
55
+ export * from './countdown';
@@ -0,0 +1,37 @@
1
+ import type { IconName } from '../../../../atoms';
2
+
3
+ /**
4
+ * Menu action entity
5
+ * Represents a single action in the long press menu
6
+ */
7
+ export interface MenuAction {
8
+ /** Unique identifier for the action */
9
+ id: string;
10
+
11
+ /** Icon name from ../../../atoms (Lucide icons) */
12
+ icon: IconName;
13
+
14
+ /** Display label for the action */
15
+ label: string;
16
+
17
+ /** Destructive action (uses error color) */
18
+ destructive?: boolean;
19
+
20
+ /** Disabled state (greyed out, not pressable) */
21
+ disabled?: boolean;
22
+ }
23
+
24
+ /**
25
+ * Predefined menu action types for common use cases
26
+ */
27
+ export const MenuActionType = {
28
+ EDIT: 'edit',
29
+ DELETE: 'delete',
30
+ SHARE: 'share',
31
+ COPY: 'copy',
32
+ ARCHIVE: 'archive',
33
+ FAVORITE: 'favorite',
34
+ MORE: 'more',
35
+ } as const;
36
+
37
+ export type MenuActionTypeValue = typeof MenuActionType[keyof typeof MenuActionType];
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @umituz/react-native-long-press-menu - Public API
3
+ *
4
+ * Context menus with long press for React Native
5
+ * Features:
6
+ * - iOS/Android-style menus
7
+ * - Haptic feedback
8
+ * - Smooth animations
9
+ * - Customizable actions
10
+ */
11
+
12
+ // Domain - Entities
13
+ export type { MenuAction, MenuActionTypeValue } from './domain/entities/MenuAction';
14
+ export { MenuActionType } from './domain/entities/MenuAction';
15
+
16
+ // Note: Add more exports as needed when implementation files are found