@flightdev/mobile 0.2.0

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.
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Platform detection utilities.
3
+ * Works without Capacitor installed - gracefully degrades.
4
+ */
5
+ type Platform = 'web' | 'ios' | 'android';
6
+ interface PlatformInfo {
7
+ /** Current platform: 'web', 'ios', or 'android' */
8
+ platform: Platform;
9
+ /** True if running as a native app (iOS or Android) */
10
+ isNative: boolean;
11
+ /** True if running on iOS */
12
+ isIOS: boolean;
13
+ /** True if running on Android */
14
+ isAndroid: boolean;
15
+ /** True if running as a web app */
16
+ isWeb: boolean;
17
+ /** True if Capacitor is available */
18
+ hasCapacitor: boolean;
19
+ }
20
+ /**
21
+ * Detect the current platform.
22
+ *
23
+ * @returns Platform information object
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const { isNative, isIOS, platform } = getPlatform();
28
+ *
29
+ * if (isNative) {
30
+ * // Use native features
31
+ * }
32
+ *
33
+ * if (isIOS) {
34
+ * // iOS-specific code
35
+ * }
36
+ * ```
37
+ */
38
+ declare function getPlatform(): PlatformInfo;
39
+ /**
40
+ * Check if a Capacitor plugin is available.
41
+ *
42
+ * @param pluginName - Name of the plugin to check
43
+ * @returns True if the plugin is registered
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * if (isPluginAvailable('Camera')) {
48
+ * // Camera plugin is installed
49
+ * }
50
+ * ```
51
+ */
52
+ declare function isPluginAvailable(pluginName: string): boolean;
53
+ /**
54
+ * Get safe area insets for notched devices.
55
+ * Returns zeros on web or when not available.
56
+ */
57
+ declare function getSafeAreaInsets(): {
58
+ top: number;
59
+ bottom: number;
60
+ left: number;
61
+ right: number;
62
+ };
63
+ /**
64
+ * Check if running in a PWA installed context.
65
+ */
66
+ declare function isPWA(): boolean;
67
+
68
+ export { type Platform as P, type PlatformInfo as a, getSafeAreaInsets as b, isPWA as c, getPlatform as g, isPluginAvailable as i };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Plugin utilities for @flightdev/mobile
3
+ *
4
+ * Helpers for working with Capacitor plugins.
5
+ */
6
+ /**
7
+ * Check if required plugins are installed.
8
+ * Useful for showing warnings or fallback UI.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const missing = checkPlugins(['Camera', 'Geolocation']);
13
+ * if (missing.length > 0) {
14
+ * console.warn('Missing plugins:', missing);
15
+ * }
16
+ * ```
17
+ */
18
+ declare function checkPlugins(pluginNames: string[]): string[];
19
+ /**
20
+ * Ensure all required plugins are available.
21
+ * Throws error if any are missing.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * try {
26
+ * requirePlugins(['Camera', 'Geolocation']);
27
+ * } catch (error) {
28
+ * console.error('Please install required plugins');
29
+ * }
30
+ * ```
31
+ */
32
+ declare function requirePlugins(pluginNames: string[]): void;
33
+ interface PluginInfo {
34
+ name: string;
35
+ package: string;
36
+ available: boolean;
37
+ description: string;
38
+ }
39
+ /**
40
+ * List of supported plugins with their status.
41
+ */
42
+ declare function getPluginInfo(): PluginInfo[];
43
+ /**
44
+ * Get installed plugins.
45
+ */
46
+ declare function getInstalledPlugins(): string[];
47
+ /**
48
+ * Get missing plugins from a required list.
49
+ */
50
+ declare function getMissingPlugins(required: string[]): PluginInfo[];
51
+
52
+ export { checkPlugins, getInstalledPlugins, getMissingPlugins, getPluginInfo, requirePlugins };
@@ -0,0 +1,104 @@
1
+ // src/platform.ts
2
+ function getCapacitor() {
3
+ try {
4
+ const Capacitor = globalThis.Capacitor;
5
+ return Capacitor || null;
6
+ } catch {
7
+ return null;
8
+ }
9
+ }
10
+ function isPluginAvailable(pluginName) {
11
+ const Capacitor = getCapacitor();
12
+ if (!Capacitor || !Capacitor.isPluginAvailable) {
13
+ return false;
14
+ }
15
+ return Capacitor.isPluginAvailable(pluginName);
16
+ }
17
+
18
+ // src/plugins/index.ts
19
+ function checkPlugins(pluginNames) {
20
+ return pluginNames.filter((name) => !isPluginAvailable(name));
21
+ }
22
+ function requirePlugins(pluginNames) {
23
+ const missing = checkPlugins(pluginNames);
24
+ if (missing.length > 0) {
25
+ throw new Error(
26
+ `Missing Capacitor plugins: ${missing.join(", ")}. Install with: npm install ${missing.map((p) => `@capacitor/${p.toLowerCase()}`).join(" ")}`
27
+ );
28
+ }
29
+ }
30
+ function getPluginInfo() {
31
+ return [
32
+ {
33
+ name: "Camera",
34
+ package: "@capacitor/camera",
35
+ available: isPluginAvailable("Camera"),
36
+ description: "Take photos and pick images"
37
+ },
38
+ {
39
+ name: "Geolocation",
40
+ package: "@capacitor/geolocation",
41
+ available: isPluginAvailable("Geolocation"),
42
+ description: "Get device location"
43
+ },
44
+ {
45
+ name: "PushNotifications",
46
+ package: "@capacitor/push-notifications",
47
+ available: isPluginAvailable("PushNotifications"),
48
+ description: "Receive push notifications"
49
+ },
50
+ {
51
+ name: "Haptics",
52
+ package: "@capacitor/haptics",
53
+ available: isPluginAvailable("Haptics"),
54
+ description: "Haptic feedback"
55
+ },
56
+ {
57
+ name: "Preferences",
58
+ package: "@capacitor/preferences",
59
+ available: isPluginAvailable("Preferences"),
60
+ description: "Key-value storage"
61
+ },
62
+ {
63
+ name: "App",
64
+ package: "@capacitor/app",
65
+ available: isPluginAvailable("App"),
66
+ description: "App lifecycle and info"
67
+ },
68
+ {
69
+ name: "StatusBar",
70
+ package: "@capacitor/status-bar",
71
+ available: isPluginAvailable("StatusBar"),
72
+ description: "Control status bar"
73
+ },
74
+ {
75
+ name: "Keyboard",
76
+ package: "@capacitor/keyboard",
77
+ available: isPluginAvailable("Keyboard"),
78
+ description: "Control keyboard"
79
+ },
80
+ {
81
+ name: "Share",
82
+ package: "@capacitor/share",
83
+ available: isPluginAvailable("Share"),
84
+ description: "Share content"
85
+ },
86
+ {
87
+ name: "Clipboard",
88
+ package: "@capacitor/clipboard",
89
+ available: isPluginAvailable("Clipboard"),
90
+ description: "Copy and paste"
91
+ }
92
+ ];
93
+ }
94
+ function getInstalledPlugins() {
95
+ return getPluginInfo().filter((p) => p.available).map((p) => p.name);
96
+ }
97
+ function getMissingPlugins(required) {
98
+ const info = getPluginInfo();
99
+ return required.map((name) => info.find((p) => p.name === name)).filter((p) => p !== void 0 && !p.available);
100
+ }
101
+
102
+ export { checkPlugins, getInstalledPlugins, getMissingPlugins, getPluginInfo, requirePlugins };
103
+ //# sourceMappingURL=index.js.map
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/platform.ts","../../src/plugins/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * Platform detection utilities.\r\n * Works without Capacitor installed - gracefully degrades.\r\n */\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport type Platform = 'web' | 'ios' | 'android';\r\n\r\nexport interface PlatformInfo {\r\n /** Current platform: 'web', 'ios', or 'android' */\r\n platform: Platform;\r\n /** True if running as a native app (iOS or Android) */\r\n isNative: boolean;\r\n /** True if running on iOS */\r\n isIOS: boolean;\r\n /** True if running on Android */\r\n isAndroid: boolean;\r\n /** True if running as a web app */\r\n isWeb: boolean;\r\n /** True if Capacitor is available */\r\n hasCapacitor: boolean;\r\n}\r\n\r\n// =============================================================================\r\n// Detection\r\n// =============================================================================\r\n\r\n/**\r\n * Get Capacitor instance if available.\r\n * Returns null if Capacitor is not installed.\r\n */\r\nfunction getCapacitor(): any {\r\n try {\r\n // Dynamic import to avoid errors when Capacitor is not installed\r\n const Capacitor = (globalThis as any).Capacitor;\r\n return Capacitor || null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Detect the current platform.\r\n * \r\n * @returns Platform information object\r\n * \r\n * @example\r\n * ```typescript\r\n * const { isNative, isIOS, platform } = getPlatform();\r\n * \r\n * if (isNative) {\r\n * // Use native features\r\n * }\r\n * \r\n * if (isIOS) {\r\n * // iOS-specific code\r\n * }\r\n * ```\r\n */\r\nexport function getPlatform(): PlatformInfo {\r\n const Capacitor = getCapacitor();\r\n\r\n if (!Capacitor) {\r\n return {\r\n platform: 'web',\r\n isNative: false,\r\n isIOS: false,\r\n isAndroid: false,\r\n isWeb: true,\r\n hasCapacitor: false,\r\n };\r\n }\r\n\r\n const platform = Capacitor.getPlatform() as Platform;\r\n const isNative = Capacitor.isNativePlatform();\r\n\r\n return {\r\n platform,\r\n isNative,\r\n isIOS: platform === 'ios',\r\n isAndroid: platform === 'android',\r\n isWeb: platform === 'web',\r\n hasCapacitor: true,\r\n };\r\n}\r\n\r\n/**\r\n * Check if a Capacitor plugin is available.\r\n * \r\n * @param pluginName - Name of the plugin to check\r\n * @returns True if the plugin is registered\r\n * \r\n * @example\r\n * ```typescript\r\n * if (isPluginAvailable('Camera')) {\r\n * // Camera plugin is installed\r\n * }\r\n * ```\r\n */\r\nexport function isPluginAvailable(pluginName: string): boolean {\r\n const Capacitor = getCapacitor();\r\n\r\n if (!Capacitor || !Capacitor.isPluginAvailable) {\r\n return false;\r\n }\r\n\r\n return Capacitor.isPluginAvailable(pluginName);\r\n}\r\n\r\n/**\r\n * Get safe area insets for notched devices.\r\n * Returns zeros on web or when not available.\r\n */\r\nexport function getSafeAreaInsets(): {\r\n top: number;\r\n bottom: number;\r\n left: number;\r\n right: number;\r\n} {\r\n // Try to get from CSS env variables\r\n if (typeof window !== 'undefined' && typeof window.getComputedStyle === 'function') {\r\n const style = getComputedStyle(document.documentElement);\r\n return {\r\n top: parseInt(style.getPropertyValue('--sat') || '0', 10),\r\n bottom: parseInt(style.getPropertyValue('--sab') || '0', 10),\r\n left: parseInt(style.getPropertyValue('--sal') || '0', 10),\r\n right: parseInt(style.getPropertyValue('--sar') || '0', 10),\r\n };\r\n }\r\n\r\n return { top: 0, bottom: 0, left: 0, right: 0 };\r\n}\r\n\r\n/**\r\n * Check if running in a PWA installed context.\r\n */\r\nexport function isPWA(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n\r\n return window.matchMedia('(display-mode: standalone)').matches ||\r\n (window.navigator as any).standalone === true;\r\n}\r\n","/**\r\n * Plugin utilities for @flightdev/mobile\r\n * \r\n * Helpers for working with Capacitor plugins.\r\n */\r\n\r\nimport { isPluginAvailable } from '../platform';\r\n\r\n// =============================================================================\r\n// Plugin Check\r\n// =============================================================================\r\n\r\n/**\r\n * Check if required plugins are installed.\r\n * Useful for showing warnings or fallback UI.\r\n * \r\n * @example\r\n * ```typescript\r\n * const missing = checkPlugins(['Camera', 'Geolocation']);\r\n * if (missing.length > 0) {\r\n * console.warn('Missing plugins:', missing);\r\n * }\r\n * ```\r\n */\r\nexport function checkPlugins(pluginNames: string[]): string[] {\r\n return pluginNames.filter(name => !isPluginAvailable(name));\r\n}\r\n\r\n/**\r\n * Ensure all required plugins are available.\r\n * Throws error if any are missing.\r\n * \r\n * @example\r\n * ```typescript\r\n * try {\r\n * requirePlugins(['Camera', 'Geolocation']);\r\n * } catch (error) {\r\n * console.error('Please install required plugins');\r\n * }\r\n * ```\r\n */\r\nexport function requirePlugins(pluginNames: string[]): void {\r\n const missing = checkPlugins(pluginNames);\r\n\r\n if (missing.length > 0) {\r\n throw new Error(\r\n `Missing Capacitor plugins: ${missing.join(', ')}. ` +\r\n `Install with: npm install ${missing.map(p => `@capacitor/${p.toLowerCase()}`).join(' ')}`\r\n );\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// Plugin Info\r\n// =============================================================================\r\n\r\ninterface PluginInfo {\r\n name: string;\r\n package: string;\r\n available: boolean;\r\n description: string;\r\n}\r\n\r\n/**\r\n * List of supported plugins with their status.\r\n */\r\nexport function getPluginInfo(): PluginInfo[] {\r\n return [\r\n {\r\n name: 'Camera',\r\n package: '@capacitor/camera',\r\n available: isPluginAvailable('Camera'),\r\n description: 'Take photos and pick images',\r\n },\r\n {\r\n name: 'Geolocation',\r\n package: '@capacitor/geolocation',\r\n available: isPluginAvailable('Geolocation'),\r\n description: 'Get device location',\r\n },\r\n {\r\n name: 'PushNotifications',\r\n package: '@capacitor/push-notifications',\r\n available: isPluginAvailable('PushNotifications'),\r\n description: 'Receive push notifications',\r\n },\r\n {\r\n name: 'Haptics',\r\n package: '@capacitor/haptics',\r\n available: isPluginAvailable('Haptics'),\r\n description: 'Haptic feedback',\r\n },\r\n {\r\n name: 'Preferences',\r\n package: '@capacitor/preferences',\r\n available: isPluginAvailable('Preferences'),\r\n description: 'Key-value storage',\r\n },\r\n {\r\n name: 'App',\r\n package: '@capacitor/app',\r\n available: isPluginAvailable('App'),\r\n description: 'App lifecycle and info',\r\n },\r\n {\r\n name: 'StatusBar',\r\n package: '@capacitor/status-bar',\r\n available: isPluginAvailable('StatusBar'),\r\n description: 'Control status bar',\r\n },\r\n {\r\n name: 'Keyboard',\r\n package: '@capacitor/keyboard',\r\n available: isPluginAvailable('Keyboard'),\r\n description: 'Control keyboard',\r\n },\r\n {\r\n name: 'Share',\r\n package: '@capacitor/share',\r\n available: isPluginAvailable('Share'),\r\n description: 'Share content',\r\n },\r\n {\r\n name: 'Clipboard',\r\n package: '@capacitor/clipboard',\r\n available: isPluginAvailable('Clipboard'),\r\n description: 'Copy and paste',\r\n },\r\n ];\r\n}\r\n\r\n/**\r\n * Get installed plugins.\r\n */\r\nexport function getInstalledPlugins(): string[] {\r\n return getPluginInfo()\r\n .filter(p => p.available)\r\n .map(p => p.name);\r\n}\r\n\r\n/**\r\n * Get missing plugins from a required list.\r\n */\r\nexport function getMissingPlugins(required: string[]): PluginInfo[] {\r\n const info = getPluginInfo();\r\n\r\n return required\r\n .map(name => info.find(p => p.name === name))\r\n .filter((p): p is PluginInfo => p !== undefined && !p.available);\r\n}\r\n"]}
@@ -0,0 +1,259 @@
1
+ import { a as PlatformInfo } from '../platform-Cq72g4Qx.js';
2
+
3
+ /**
4
+ * React hooks for @flightdev/mobile
5
+ *
6
+ * Provides React-friendly wrappers around Capacitor plugins.
7
+ * All hooks gracefully degrade on web - no errors if plugin not installed.
8
+ *
9
+ * Philosophy: Flight doesn't impose - use only the hooks you need.
10
+ * Each Capacitor plugin is an optional peer dependency.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { usePlatform, useCamera, useGeolocation } from '@flightdev/mobile/react';
15
+ *
16
+ * function App() {
17
+ * const { isNative, isIOS } = usePlatform();
18
+ * const { takePhoto } = useCamera();
19
+ * const { position, getCurrentPosition } = useGeolocation();
20
+ *
21
+ * // ...
22
+ * }
23
+ * ```
24
+ */
25
+
26
+ /**
27
+ * Get current platform information.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * function App() {
32
+ * const { isNative, isIOS, isAndroid, isWeb } = usePlatform();
33
+ *
34
+ * if (isNative) {
35
+ * return <NativeApp />;
36
+ * }
37
+ *
38
+ * return <WebApp />;
39
+ * }
40
+ * ```
41
+ */
42
+ declare function usePlatform(): PlatformInfo;
43
+ interface CameraResult {
44
+ /** Path to the image that can be used as src */
45
+ webPath?: string;
46
+ /** Base64 encoded image data */
47
+ base64String?: string;
48
+ /** Platform-specific path */
49
+ path?: string;
50
+ /** Image format (jpeg, png, etc.) */
51
+ format?: string;
52
+ /** Whether the image was saved to gallery */
53
+ saved?: boolean;
54
+ }
55
+ interface UseCameraOptions {
56
+ /** Image quality (0-100) */
57
+ quality?: number;
58
+ /** Allow editing before returning */
59
+ allowEditing?: boolean;
60
+ /** Save to photo gallery */
61
+ saveToGallery?: boolean;
62
+ /** Width constraint */
63
+ width?: number;
64
+ /** Height constraint */
65
+ height?: number;
66
+ }
67
+ interface UseCameraReturn {
68
+ /** Take a photo with the camera */
69
+ takePhoto: (options?: UseCameraOptions) => Promise<CameraResult | null>;
70
+ /** Pick an image from gallery */
71
+ pickImage: (options?: UseCameraOptions) => Promise<CameraResult | null>;
72
+ /** Camera is available */
73
+ available: boolean;
74
+ }
75
+ /**
76
+ * Camera hook for taking photos and picking images.
77
+ * Requires @capacitor/camera to be installed.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * function PhotoCapture() {
82
+ * const { takePhoto, pickImage, available } = useCamera();
83
+ *
84
+ * const handleCapture = async () => {
85
+ * const photo = await takePhoto({ quality: 90 });
86
+ * if (photo?.webPath) {
87
+ * setImage(photo.webPath);
88
+ * }
89
+ * };
90
+ *
91
+ * if (!available) return <p>Camera not available</p>;
92
+ *
93
+ * return <button onClick={handleCapture}>Take Photo</button>;
94
+ * }
95
+ * ```
96
+ */
97
+ declare function useCamera(): UseCameraReturn;
98
+ interface GeolocationPosition {
99
+ coords: {
100
+ latitude: number;
101
+ longitude: number;
102
+ accuracy: number;
103
+ altitude: number | null;
104
+ altitudeAccuracy: number | null;
105
+ heading: number | null;
106
+ speed: number | null;
107
+ };
108
+ timestamp: number;
109
+ }
110
+ interface UseGeolocationReturn {
111
+ /** Current position (null until fetched) */
112
+ position: GeolocationPosition | null;
113
+ /** Fetch error if any */
114
+ error: Error | null;
115
+ /** Loading state */
116
+ loading: boolean;
117
+ /** Get current position */
118
+ getCurrentPosition: () => Promise<GeolocationPosition | null>;
119
+ /** Start watching position changes */
120
+ watchPosition: (callback: (pos: GeolocationPosition) => void) => Promise<string | null>;
121
+ /** Stop watching position */
122
+ clearWatch: (watchId: string) => Promise<void>;
123
+ /** Geolocation is available */
124
+ available: boolean;
125
+ }
126
+ /**
127
+ * Geolocation hook for getting device position.
128
+ * Requires @capacitor/geolocation to be installed.
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * function LocationTracker() {
133
+ * const { position, error, loading, getCurrentPosition, available } = useGeolocation();
134
+ *
135
+ * if (!available) return <p>Geolocation not available</p>;
136
+ * if (loading) return <p>Getting location...</p>;
137
+ * if (error) return <p>Error: {error.message}</p>;
138
+ *
139
+ * return (
140
+ * <div>
141
+ * <p>Lat: {position?.coords.latitude}</p>
142
+ * <p>Lng: {position?.coords.longitude}</p>
143
+ * <button onClick={getCurrentPosition}>Refresh</button>
144
+ * </div>
145
+ * );
146
+ * }
147
+ * ```
148
+ */
149
+ declare function useGeolocation(): UseGeolocationReturn;
150
+ interface UsePushNotificationsReturn {
151
+ /** FCM/APNs token for the device */
152
+ token: string | null;
153
+ /** Request permission and register for notifications */
154
+ requestPermission: () => Promise<boolean>;
155
+ /** Add listener for notification received */
156
+ onNotificationReceived: (callback: (notification: any) => void) => Promise<() => void>;
157
+ /** Add listener for notification action */
158
+ onNotificationAction: (callback: (notification: any) => void) => Promise<() => void>;
159
+ /** Push notifications available */
160
+ available: boolean;
161
+ }
162
+ /**
163
+ * Push notifications hook.
164
+ * Requires @capacitor/push-notifications to be installed.
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * function NotificationSetup() {
169
+ * const { token, requestPermission, onNotificationReceived, available } = usePushNotifications();
170
+ *
171
+ * useEffect(() => {
172
+ * if (!available) return;
173
+ *
174
+ * requestPermission();
175
+ *
176
+ * const cleanup = onNotificationReceived((notification) => {
177
+ * console.log('Received:', notification);
178
+ * });
179
+ *
180
+ * return () => { cleanup.then(fn => fn?.()); };
181
+ * }, []);
182
+ *
183
+ * return <p>Token: {token}</p>;
184
+ * }
185
+ * ```
186
+ */
187
+ declare function usePushNotifications(): UsePushNotificationsReturn;
188
+ interface UseHapticsReturn {
189
+ /** Light impact feedback */
190
+ impact: (style?: 'light' | 'medium' | 'heavy') => Promise<void>;
191
+ /** Notification feedback */
192
+ notification: (type?: 'success' | 'warning' | 'error') => Promise<void>;
193
+ /** Selection feedback */
194
+ selection: () => Promise<void>;
195
+ /** Vibrate for duration */
196
+ vibrate: (duration?: number) => Promise<void>;
197
+ /** Haptics available */
198
+ available: boolean;
199
+ }
200
+ /**
201
+ * Haptic feedback hook.
202
+ * Requires @capacitor/haptics to be installed.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * function HapticButton() {
207
+ * const { impact, notification, available } = useHaptics();
208
+ *
209
+ * const handlePress = async () => {
210
+ * await impact('medium');
211
+ * // Do action
212
+ * };
213
+ *
214
+ * const handleSuccess = async () => {
215
+ * await notification('success');
216
+ * };
217
+ *
218
+ * return <button onClick={handlePress}>Press me</button>;
219
+ * }
220
+ * ```
221
+ */
222
+ declare function useHaptics(): UseHapticsReturn;
223
+ interface UseStorageReturn {
224
+ /** Get a value from storage */
225
+ get: (key: string) => Promise<string | null>;
226
+ /** Set a value in storage */
227
+ set: (key: string, value: string) => Promise<void>;
228
+ /** Remove a value from storage */
229
+ remove: (key: string) => Promise<void>;
230
+ /** Get all keys */
231
+ keys: () => Promise<string[]>;
232
+ /** Clear all storage */
233
+ clear: () => Promise<void>;
234
+ /** Storage available */
235
+ available: boolean;
236
+ }
237
+ /**
238
+ * Secure storage hook using Capacitor Preferences.
239
+ * Falls back to localStorage on web.
240
+ * Requires @capacitor/preferences to be installed for native.
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * function UserSettings() {
245
+ * const { get, set, remove } = useStorage();
246
+ *
247
+ * const saveTheme = async (theme: string) => {
248
+ * await set('theme', theme);
249
+ * };
250
+ *
251
+ * const loadTheme = async () => {
252
+ * return await get('theme') ?? 'light';
253
+ * };
254
+ * }
255
+ * ```
256
+ */
257
+ declare function useStorage(): UseStorageReturn;
258
+
259
+ export { useCamera, useGeolocation, useHaptics, usePlatform, usePushNotifications, useStorage };