@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,205 @@
1
+ /**
2
+ * Sharing Domain - Barrel Export
3
+ *
4
+ * Provides system share sheet functionality using expo-sharing.
5
+ * Optional domain - disabled by default (opt-in).
6
+ *
7
+ * @domain sharing
8
+ * @enabled false (Apps that need file sharing - Opt-in)
9
+ *
10
+ * ARCHITECTURE:
11
+ * - Domain Layer: Entities (share types, MIME types, utilities)
12
+ * - Infrastructure Layer: Services (SharingService)
13
+ * - Presentation Layer: Hooks (useSharing)
14
+ *
15
+ * DEPENDENCIES:
16
+ * - expo-sharing (system share sheet)
17
+ *
18
+ * FEATURES:
19
+ * - Share files via system share sheet
20
+ * - Automatic MIME type detection
21
+ * - Platform-specific options (UTI for iOS, dialogTitle for Android)
22
+ * - Share availability check
23
+ * - Multiple file sharing (sequential)
24
+ *
25
+ * USAGE:
26
+ *
27
+ * Basic Sharing:
28
+ * ```typescript
29
+ * import { useSharing } from '@umituz/react-native-sharing';
30
+ *
31
+ * const { share, isAvailable, isSharing } = useSharing();
32
+ *
33
+ * if (!isAvailable) {
34
+ * return <Text>Sharing not available</Text>;
35
+ * }
36
+ *
37
+ * const handleShare = async () => {
38
+ * const success = await share('file:///path/to/file.jpg', {
39
+ * dialogTitle: 'Share Photo',
40
+ * mimeType: 'image/jpeg',
41
+ * });
42
+ *
43
+ * if (success) {
44
+ * console.log('Shared successfully');
45
+ * }
46
+ * };
47
+ *
48
+ * <AtomicButton onPress={handleShare} loading={isSharing}>
49
+ * Share
50
+ * </AtomicButton>
51
+ * ```
52
+ *
53
+ * Auto-Detect MIME Type:
54
+ * ```typescript
55
+ * import { useSharing } from '@umituz/react-native-sharing';
56
+ *
57
+ * const { shareWithAutoType } = useSharing();
58
+ *
59
+ * // MIME type auto-detected from .pdf extension
60
+ * await shareWithAutoType(
61
+ * 'file:///path/to/document.pdf',
62
+ * 'document.pdf',
63
+ * 'Share Document'
64
+ * );
65
+ *
66
+ * // MIME type auto-detected from .jpg extension
67
+ * await shareWithAutoType(
68
+ * 'file:///path/to/photo.jpg',
69
+ * 'photo.jpg',
70
+ * 'Share Photo'
71
+ * );
72
+ * ```
73
+ *
74
+ * Share with media Integration:
75
+ * ```typescript
76
+ * import { useMedia } from '@umituz/react-native-media';
77
+ * import { useSharing } from '@umituz/react-native-sharing';
78
+ * import { FileSystemService } from '@umituz/react-native-filesystem';
79
+ *
80
+ * const { pickImage } = useMedia();
81
+ * const { shareWithAutoType } = useSharing();
82
+ *
83
+ * const handlePickAndShare = async () => {
84
+ * // Pick image
85
+ * const result = await pickImage();
86
+ * if (result.canceled || !result.assets?.[0]?.uri) return;
87
+ *
88
+ * // Save to filesystem
89
+ * const savedPath = await FileSystemService.copyToDocuments(
90
+ * result.assets[0].uri,
91
+ * 'shared_image.jpg'
92
+ * );
93
+ *
94
+ * if (!savedPath.success || !savedPath.uri) return;
95
+ *
96
+ * // Share via system sheet
97
+ * await shareWithAutoType(savedPath.uri, 'shared_image.jpg', 'Share Photo');
98
+ * };
99
+ * ```
100
+ *
101
+ * Share Multiple Files:
102
+ * ```typescript
103
+ * import { useSharing } from '@umituz/react-native-sharing';
104
+ *
105
+ * const { shareMultiple } = useSharing();
106
+ *
107
+ * const handleShareMultiple = async () => {
108
+ * const uris = [
109
+ * 'file:///path/to/file1.jpg',
110
+ * 'file:///path/to/file2.jpg',
111
+ * 'file:///path/to/file3.jpg',
112
+ * ];
113
+ *
114
+ * await shareMultiple(uris, {
115
+ * dialogTitle: 'Share Photos',
116
+ * mimeType: 'image/jpeg',
117
+ * });
118
+ * };
119
+ * ```
120
+ *
121
+ * MIME Type Utilities:
122
+ * ```typescript
123
+ * import { SharingUtils, MIME_TYPES } from '@umituz/react-native-sharing';
124
+ *
125
+ * // Get MIME type from extension
126
+ * const mimeType = SharingUtils.getMimeTypeFromExtension('document.pdf');
127
+ * // Returns: 'application/pdf'
128
+ *
129
+ * // Get UTI for iOS
130
+ * const uti = SharingUtils.getUTIFromExtension('photo.jpg');
131
+ * // Returns: 'public.jpeg'
132
+ *
133
+ * // Prepare full options
134
+ * const options = SharingUtils.prepareShareOptions('file.pdf', 'Share Document');
135
+ * // Returns: { dialogTitle, mimeType, UTI }
136
+ *
137
+ * // Use predefined MIME types
138
+ * await share(uri, { mimeType: MIME_TYPES.PDF });
139
+ * await share(uri, { mimeType: MIME_TYPES.IMAGE_JPEG });
140
+ * await share(uri, { mimeType: MIME_TYPES.VIDEO_MP4 });
141
+ * ```
142
+ *
143
+ * Direct Service Usage (Rare):
144
+ * ```typescript
145
+ * import { SharingService } from '@umituz/react-native-sharing';
146
+ *
147
+ * // Check availability
148
+ * const isAvailable = await SharingService.isAvailable();
149
+ *
150
+ * // Share file
151
+ * const result = await SharingService.shareFile(uri, options);
152
+ * if (result.success) {
153
+ * console.log('Shared');
154
+ * } else {
155
+ * console.error(result.error);
156
+ * }
157
+ * ```
158
+ *
159
+ * BENEFITS:
160
+ * - Native system share sheet (OS-provided UI)
161
+ * - Automatic MIME type detection from filename
162
+ * - Platform-specific options (iOS UTI, Android dialogTitle)
163
+ * - Share availability check before attempting
164
+ * - Type-safe share operations
165
+ * - Error handling with state management
166
+ * - Works with all file types
167
+ *
168
+ * USE CASES:
169
+ * - Share photos/videos from gallery
170
+ * - Export reports/documents
171
+ * - Share app-generated content
172
+ * - Social media sharing
173
+ * - File backup/export
174
+ * - Collaborative file sharing
175
+ *
176
+ * @see https://docs.expo.dev/versions/latest/sdk/sharing/
177
+ */
178
+
179
+ // ============================================================================
180
+ // DOMAIN LAYER - ENTITIES
181
+ // ============================================================================
182
+
183
+ export type {
184
+ ShareOptions,
185
+ ShareResult,
186
+ } from './domain/entities/Share';
187
+
188
+ export {
189
+ MIME_TYPES,
190
+ UTI_TYPES,
191
+ SHARING_CONSTANTS,
192
+ SharingUtils,
193
+ } from './domain/entities/Share';
194
+
195
+ // ============================================================================
196
+ // INFRASTRUCTURE LAYER - SERVICES
197
+ // ============================================================================
198
+
199
+ export { SharingService } from './infrastructure/services/SharingService';
200
+
201
+ // ============================================================================
202
+ // PRESENTATION LAYER - HOOKS
203
+ // ============================================================================
204
+
205
+ export { useSharing } from './presentation/hooks/useSharing';
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Sharing Domain - Sharing Service
3
+ *
4
+ * Service for sharing files using expo-sharing.
5
+ * Provides abstraction layer for system share sheet.
6
+ *
7
+ * @domain sharing
8
+ * @layer infrastructure/services
9
+ */
10
+
11
+ import * as Sharing from 'expo-sharing';
12
+ import * as FileSystem from 'expo-file-system/legacy';
13
+ import type { ShareOptions, ShareResult } from '../../domain/entities/Share';
14
+ import { SharingUtils } from '../../domain/entities/Share';
15
+
16
+ /**
17
+ * Sharing service for sharing files via system share sheet
18
+ */
19
+ export class SharingService {
20
+ /**
21
+ * Check if sharing is available on device
22
+ */
23
+ static async isAvailable(): Promise<boolean> {
24
+ try {
25
+ return await Sharing.isAvailableAsync();
26
+ } catch (error) {
27
+ return false;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Share a file via system share sheet
33
+ *
34
+ * @param uri - File URI to share (can be local or remote http/https)
35
+ * @param options - Share options (dialog title, MIME type, UTI)
36
+ * @returns ShareResult with success status
37
+ *
38
+ * USAGE:
39
+ * ```typescript
40
+ * // Basic share (local)
41
+ * await SharingService.shareFile('file:///path/to/image.jpg');
42
+ *
43
+ * // Remote file (will be downloaded)
44
+ * await SharingService.shareFile('https://example.com/image.jpg');
45
+ * ```
46
+ */
47
+ static async shareFile(uri: string, options?: ShareOptions): Promise<ShareResult> {
48
+ try {
49
+ // Check availability
50
+ const available = await SharingService.isAvailable();
51
+ if (!available) {
52
+ return {
53
+ success: false,
54
+ error: 'Sharing is not available on this device',
55
+ };
56
+ }
57
+
58
+ let shareUri = uri;
59
+
60
+ // Handle remote URLs
61
+ if (uri.startsWith('http://') || uri.startsWith('https://')) {
62
+ try {
63
+ const filename = uri.split('/').pop()?.split('?')[0] || `share-${Date.now()}`;
64
+ // Ensure we have an extension if possible, or default to bin/jpg?
65
+ // Better to rely on what we have, or let the caller specify mimeType to infer extension?
66
+ // For now, nice and simple:
67
+ const localUri = `${FileSystem.cacheDirectory}${filename}`;
68
+ const { uri: downloadedUri, status } = await FileSystem.downloadAsync(uri, localUri);
69
+
70
+ if (status !== 200) {
71
+ return { success: false, error: `Failed to download file: ${status}` };
72
+ }
73
+ shareUri = downloadedUri;
74
+ } catch (downloadError) {
75
+ return {
76
+ success: false,
77
+ error: downloadError instanceof Error ? downloadError.message : 'Failed to download file'
78
+ };
79
+ }
80
+ }
81
+
82
+ // Share file
83
+ await Sharing.shareAsync(shareUri, options);
84
+
85
+ return { success: true };
86
+ } catch (error) {
87
+ return {
88
+ success: false,
89
+ error: error instanceof Error ? error.message : 'Failed to share file',
90
+ };
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Share a file with automatic MIME type detection
96
+ *
97
+ * @param uri - File URI to share
98
+ * @param filename - Filename (used for MIME type detection)
99
+ * @param dialogTitle - Optional dialog title (Android)
100
+ * @returns ShareResult with success status
101
+ *
102
+ * USAGE:
103
+ * ```typescript
104
+ * // Auto-detect MIME type from filename
105
+ * await SharingService.shareWithAutoType(
106
+ * 'file:///path/to/file.jpg',
107
+ * 'photo.jpg',
108
+ * 'Share Photo'
109
+ * );
110
+ * ```
111
+ */
112
+ static async shareWithAutoType(
113
+ uri: string,
114
+ filename: string,
115
+ dialogTitle?: string
116
+ ): Promise<ShareResult> {
117
+ const options = SharingUtils.prepareShareOptions(filename, dialogTitle);
118
+ return await SharingService.shareFile(uri, options);
119
+ }
120
+
121
+ /**
122
+ * Share multiple files (if supported)
123
+ *
124
+ * NOTE: expo-sharing currently only supports sharing one file at a time.
125
+ * This method shares files sequentially.
126
+ *
127
+ * @param uris - Array of file URIs to share
128
+ * @param options - Share options
129
+ * @returns ShareResult with success status
130
+ */
131
+ static async shareMultipleFiles(
132
+ uris: string[],
133
+ options?: ShareOptions
134
+ ): Promise<ShareResult> {
135
+ try {
136
+ if (uris.length === 0) {
137
+ return {
138
+ success: false,
139
+ error: 'No files to share',
140
+ };
141
+ }
142
+
143
+ // Check availability
144
+ const available = await SharingService.isAvailable();
145
+ if (!available) {
146
+ return {
147
+ success: false,
148
+ error: 'Sharing is not available on this device',
149
+ };
150
+ }
151
+
152
+ // Share files sequentially
153
+ for (const uri of uris) {
154
+ await Sharing.shareAsync(uri, options);
155
+ }
156
+
157
+ return { success: true };
158
+ } catch (error) {
159
+ return {
160
+ success: false,
161
+ error: error instanceof Error ? error.message : 'Failed to share files',
162
+ };
163
+ }
164
+ }
165
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Sharing Domain - useSharing Hook
3
+ *
4
+ * React hook for sharing files.
5
+ * Provides system share sheet functionality with state management.
6
+ *
7
+ * @domain sharing
8
+ * @layer presentation/hooks
9
+ */
10
+
11
+ import { useState, useCallback, useEffect } from 'react';
12
+ import { SharingService } from '../../infrastructure/services/SharingService';
13
+ import type { ShareOptions } from '../../domain/entities/Share';
14
+
15
+ /**
16
+ * useSharing hook for sharing files via system share sheet
17
+ *
18
+ * USAGE:
19
+ * ```typescript
20
+ * const { share, shareWithAutoType, isAvailable, isSharing } = useSharing();
21
+ *
22
+ * // Check availability
23
+ * if (!isAvailable) {
24
+ * return <Text>Sharing not available</Text>;
25
+ * }
26
+ *
27
+ * // Basic share
28
+ * const handleShare = async () => {
29
+ * await share('file:///path/to/file.jpg', {
30
+ * dialogTitle: 'Share Photo',
31
+ * mimeType: 'image/jpeg',
32
+ * });
33
+ * };
34
+ *
35
+ * // Auto-detect MIME type
36
+ * const handleShareAuto = async () => {
37
+ * await shareWithAutoType(
38
+ * 'file:///path/to/document.pdf',
39
+ * 'document.pdf',
40
+ * 'Share Document'
41
+ * );
42
+ * };
43
+ * ```
44
+ */
45
+ export const useSharing = () => {
46
+ const [isAvailable, setIsAvailable] = useState(false);
47
+ const [isSharing, setIsSharing] = useState(false);
48
+ const [error, setError] = useState<string | null>(null);
49
+
50
+ /**
51
+ * Check sharing availability on mount
52
+ */
53
+ useEffect(() => {
54
+ const checkAvailability = async () => {
55
+ const available = await SharingService.isAvailable();
56
+ setIsAvailable(available);
57
+ };
58
+
59
+ checkAvailability();
60
+ }, []);
61
+
62
+ /**
63
+ * Share a file via system share sheet
64
+ */
65
+ const share = useCallback(async (uri: string, options?: ShareOptions): Promise<boolean> => {
66
+ setIsSharing(true);
67
+ setError(null);
68
+
69
+ try {
70
+ const result = await SharingService.shareFile(uri, options);
71
+
72
+ if (!result.success) {
73
+ setError(result.error || 'Failed to share file');
74
+ return false;
75
+ }
76
+
77
+ return true;
78
+ } catch (err) {
79
+ const errorMessage = err instanceof Error ? err.message : 'Failed to share file';
80
+ setError(errorMessage);
81
+ return false;
82
+ } finally {
83
+ setIsSharing(false);
84
+ }
85
+ }, []);
86
+
87
+ /**
88
+ * Share file with automatic MIME type detection
89
+ */
90
+ const shareWithAutoType = useCallback(
91
+ async (uri: string, filename: string, dialogTitle?: string): Promise<boolean> => {
92
+ setIsSharing(true);
93
+ setError(null);
94
+
95
+ try {
96
+ const result = await SharingService.shareWithAutoType(uri, filename, dialogTitle);
97
+
98
+ if (!result.success) {
99
+ setError(result.error || 'Failed to share file');
100
+ return false;
101
+ }
102
+
103
+ return true;
104
+ } catch (err) {
105
+ const errorMessage = err instanceof Error ? err.message : 'Failed to share file';
106
+ setError(errorMessage);
107
+ return false;
108
+ } finally {
109
+ setIsSharing(false);
110
+ }
111
+ },
112
+ []
113
+ );
114
+
115
+ /**
116
+ * Share multiple files
117
+ */
118
+ const shareMultiple = useCallback(
119
+ async (uris: string[], options?: ShareOptions): Promise<boolean> => {
120
+ setIsSharing(true);
121
+ setError(null);
122
+
123
+ try {
124
+ const result = await SharingService.shareMultipleFiles(uris, options);
125
+
126
+ if (!result.success) {
127
+ setError(result.error || 'Failed to share files');
128
+ return false;
129
+ }
130
+
131
+ return true;
132
+ } catch (err) {
133
+ const errorMessage = err instanceof Error ? err.message : 'Failed to share files';
134
+ setError(errorMessage);
135
+ return false;
136
+ } finally {
137
+ setIsSharing(false);
138
+ }
139
+ },
140
+ []
141
+ );
142
+
143
+ return {
144
+ // Functions
145
+ share,
146
+ shareWithAutoType,
147
+ shareMultiple,
148
+
149
+ // State
150
+ isAvailable,
151
+ isSharing,
152
+ error,
153
+ };
154
+ };