@aspect-ops/exon-ui 0.0.1 → 0.0.3

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 (178) hide show
  1. package/README.md +438 -0
  2. package/dist/components/ActionSheet/ActionSheet.svelte +270 -0
  3. package/dist/components/ActionSheet/ActionSheet.svelte.d.ts +12 -0
  4. package/dist/components/ActionSheet/ActionSheetItem.svelte +151 -0
  5. package/dist/components/ActionSheet/ActionSheetItem.svelte.d.ts +10 -0
  6. package/dist/components/ActionSheet/index.d.ts +3 -0
  7. package/dist/components/ActionSheet/index.js +2 -0
  8. package/dist/components/Alert/Alert.svelte +165 -0
  9. package/dist/components/Alert/Alert.svelte.d.ts +11 -0
  10. package/dist/components/Alert/index.d.ts +1 -0
  11. package/dist/components/Alert/index.js +1 -0
  12. package/dist/components/AspectRatio/AspectRatio.svelte +42 -0
  13. package/dist/components/AspectRatio/AspectRatio.svelte.d.ts +9 -0
  14. package/dist/components/AspectRatio/index.d.ts +1 -0
  15. package/dist/components/AspectRatio/index.js +1 -0
  16. package/dist/components/Avatar/Avatar.svelte +147 -0
  17. package/dist/components/Avatar/Avatar.svelte.d.ts +12 -0
  18. package/dist/components/Avatar/AvatarGroup.svelte +153 -0
  19. package/dist/components/Avatar/AvatarGroup.svelte.d.ts +12 -0
  20. package/dist/components/Avatar/index.d.ts +2 -0
  21. package/dist/components/Avatar/index.js +2 -0
  22. package/dist/components/BottomSheet/BottomSheet.svelte +230 -0
  23. package/dist/components/BottomSheet/BottomSheet.svelte.d.ts +7 -0
  24. package/dist/components/BottomSheet/BottomSheetBody.svelte +20 -0
  25. package/dist/components/BottomSheet/BottomSheetBody.svelte.d.ts +7 -0
  26. package/dist/components/BottomSheet/BottomSheetHeader.svelte +27 -0
  27. package/dist/components/BottomSheet/BottomSheetHeader.svelte.d.ts +7 -0
  28. package/dist/components/BottomSheet/index.d.ts +3 -0
  29. package/dist/components/BottomSheet/index.js +3 -0
  30. package/dist/components/Box/Box.svelte +41 -0
  31. package/dist/components/Box/Box.svelte.d.ts +7 -0
  32. package/dist/components/Box/index.d.ts +1 -0
  33. package/dist/components/Box/index.js +1 -0
  34. package/dist/components/Card/Card.svelte +95 -0
  35. package/dist/components/Card/Card.svelte.d.ts +10 -0
  36. package/dist/components/Card/CardBody.svelte +32 -0
  37. package/dist/components/Card/CardBody.svelte.d.ts +7 -0
  38. package/dist/components/Card/CardFooter.svelte +34 -0
  39. package/dist/components/Card/CardFooter.svelte.d.ts +7 -0
  40. package/dist/components/Card/CardHeader.svelte +67 -0
  41. package/dist/components/Card/CardHeader.svelte.d.ts +9 -0
  42. package/dist/components/Card/index.d.ts +4 -0
  43. package/dist/components/Card/index.js +4 -0
  44. package/dist/components/Center/Center.svelte +28 -0
  45. package/dist/components/Center/Center.svelte.d.ts +8 -0
  46. package/dist/components/Center/index.d.ts +1 -0
  47. package/dist/components/Center/index.js +1 -0
  48. package/dist/components/Container/Container.svelte +58 -0
  49. package/dist/components/Container/Container.svelte.d.ts +10 -0
  50. package/dist/components/Container/index.d.ts +1 -0
  51. package/dist/components/Container/index.js +1 -0
  52. package/dist/components/Divider/Divider.svelte +38 -0
  53. package/dist/components/Divider/Divider.svelte.d.ts +9 -0
  54. package/dist/components/Divider/index.d.ts +1 -0
  55. package/dist/components/Divider/index.js +1 -0
  56. package/dist/components/EmptyState/EmptyState.svelte +164 -0
  57. package/dist/components/EmptyState/EmptyState.svelte.d.ts +12 -0
  58. package/dist/components/EmptyState/index.d.ts +1 -0
  59. package/dist/components/EmptyState/index.js +1 -0
  60. package/dist/components/FAB/FAB.svelte +242 -0
  61. package/dist/components/FAB/FAB.svelte.d.ts +9 -0
  62. package/dist/components/FAB/FABGroup.svelte +449 -0
  63. package/dist/components/FAB/FABGroup.svelte.d.ts +9 -0
  64. package/dist/components/FAB/index.d.ts +3 -0
  65. package/dist/components/FAB/index.js +2 -0
  66. package/dist/components/Grid/Grid.svelte +136 -0
  67. package/dist/components/Grid/Grid.svelte.d.ts +12 -0
  68. package/dist/components/Grid/GridItem.svelte +21 -0
  69. package/dist/components/Grid/GridItem.svelte.d.ts +7 -0
  70. package/dist/components/Grid/index.d.ts +2 -0
  71. package/dist/components/Grid/index.js +2 -0
  72. package/dist/components/List/List.svelte +42 -0
  73. package/dist/components/List/List.svelte.d.ts +18 -0
  74. package/dist/components/List/ListItem.svelte +139 -0
  75. package/dist/components/List/ListItem.svelte.d.ts +36 -0
  76. package/dist/components/List/index.d.ts +2 -0
  77. package/dist/components/List/index.js +2 -0
  78. package/dist/components/Modal/Modal.svelte +204 -0
  79. package/dist/components/Modal/Modal.svelte.d.ts +7 -0
  80. package/dist/components/Modal/ModalBody.svelte +50 -0
  81. package/dist/components/Modal/ModalBody.svelte.d.ts +7 -0
  82. package/dist/components/Modal/ModalFooter.svelte +37 -0
  83. package/dist/components/Modal/ModalFooter.svelte.d.ts +7 -0
  84. package/dist/components/Modal/ModalHeader.svelte +73 -0
  85. package/dist/components/Modal/ModalHeader.svelte.d.ts +7 -0
  86. package/dist/components/Modal/index.d.ts +4 -0
  87. package/dist/components/Modal/index.js +4 -0
  88. package/dist/components/Popover/Popover.svelte +14 -0
  89. package/dist/components/Popover/Popover.svelte.d.ts +7 -0
  90. package/dist/components/Popover/PopoverContent.svelte +63 -0
  91. package/dist/components/Popover/PopoverContent.svelte.d.ts +7 -0
  92. package/dist/components/Popover/PopoverTrigger.svelte +14 -0
  93. package/dist/components/Popover/PopoverTrigger.svelte.d.ts +7 -0
  94. package/dist/components/Popover/index.d.ts +3 -0
  95. package/dist/components/Popover/index.js +3 -0
  96. package/dist/components/Progress/ProgressBar.svelte +86 -0
  97. package/dist/components/Progress/ProgressBar.svelte.d.ts +11 -0
  98. package/dist/components/Progress/ProgressCircle.svelte +134 -0
  99. package/dist/components/Progress/ProgressCircle.svelte.d.ts +12 -0
  100. package/dist/components/Progress/Spinner.svelte +68 -0
  101. package/dist/components/Progress/Spinner.svelte.d.ts +8 -0
  102. package/dist/components/Progress/index.d.ts +3 -0
  103. package/dist/components/Progress/index.js +3 -0
  104. package/dist/components/PullToRefresh/PullToRefresh.svelte +304 -0
  105. package/dist/components/PullToRefresh/PullToRefresh.svelte.d.ts +20 -0
  106. package/dist/components/PullToRefresh/index.d.ts +1 -0
  107. package/dist/components/PullToRefresh/index.js +1 -0
  108. package/dist/components/SafeArea/SafeArea.svelte +33 -0
  109. package/dist/components/SafeArea/SafeArea.svelte.d.ts +7 -0
  110. package/dist/components/Select/Select.svelte +55 -12
  111. package/dist/components/Skeleton/Skeleton.svelte +59 -0
  112. package/dist/components/Skeleton/Skeleton.svelte.d.ts +10 -0
  113. package/dist/components/Skeleton/index.d.ts +1 -0
  114. package/dist/components/Skeleton/index.js +1 -0
  115. package/dist/components/Spacer/Spacer.svelte +56 -0
  116. package/dist/components/Spacer/Spacer.svelte.d.ts +6 -0
  117. package/dist/components/Spacer/index.d.ts +1 -0
  118. package/dist/components/Spacer/index.js +1 -0
  119. package/dist/components/Stack/Stack.svelte +117 -0
  120. package/dist/components/Stack/Stack.svelte.d.ts +13 -0
  121. package/dist/components/Stack/index.d.ts +1 -0
  122. package/dist/components/Stack/index.js +1 -0
  123. package/dist/components/SwipeActions/SwipeAction.svelte +43 -0
  124. package/dist/components/SwipeActions/SwipeAction.svelte.d.ts +8 -0
  125. package/dist/components/SwipeActions/SwipeActions.svelte +193 -0
  126. package/dist/components/SwipeActions/SwipeActions.svelte.d.ts +9 -0
  127. package/dist/components/SwipeActions/index.d.ts +2 -0
  128. package/dist/components/SwipeActions/index.js +2 -0
  129. package/dist/components/Switch/Switch.svelte +29 -9
  130. package/dist/components/Table/Table.svelte +175 -0
  131. package/dist/components/Table/Table.svelte.d.ts +38 -0
  132. package/dist/components/Table/TableBody.svelte +26 -0
  133. package/dist/components/Table/TableBody.svelte.d.ts +13 -0
  134. package/dist/components/Table/TableCell.svelte +85 -0
  135. package/dist/components/Table/TableCell.svelte.d.ts +28 -0
  136. package/dist/components/Table/TableHead.svelte +36 -0
  137. package/dist/components/Table/TableHead.svelte.d.ts +13 -0
  138. package/dist/components/Table/TableHeader.svelte +217 -0
  139. package/dist/components/Table/TableHeader.svelte.d.ts +32 -0
  140. package/dist/components/Table/TableRow.svelte +92 -0
  141. package/dist/components/Table/TableRow.svelte.d.ts +28 -0
  142. package/dist/components/Table/index.d.ts +6 -0
  143. package/dist/components/Table/index.js +6 -0
  144. package/dist/components/Tag/Tag.svelte +189 -0
  145. package/dist/components/Tag/Tag.svelte.d.ts +13 -0
  146. package/dist/components/Tag/index.d.ts +1 -0
  147. package/dist/components/Tag/index.js +1 -0
  148. package/dist/components/Toast/Toast.svelte +241 -0
  149. package/dist/components/Toast/Toast.svelte.d.ts +18 -0
  150. package/dist/components/Toast/ToastContainer.svelte +110 -0
  151. package/dist/components/Toast/ToastContainer.svelte.d.ts +8 -0
  152. package/dist/components/Toast/index.d.ts +3 -0
  153. package/dist/components/Toast/index.js +3 -0
  154. package/dist/components/Toast/toast.d.ts +13 -0
  155. package/dist/components/Toast/toast.js +55 -0
  156. package/dist/components/Tooltip/Tooltip.svelte +71 -0
  157. package/dist/components/Tooltip/Tooltip.svelte.d.ts +7 -0
  158. package/dist/components/Tooltip/index.d.ts +2 -0
  159. package/dist/components/Tooltip/index.js +1 -0
  160. package/dist/index.d.ts +29 -1
  161. package/dist/index.js +32 -0
  162. package/dist/styles/tokens.css +5 -0
  163. package/dist/types/data-display.d.ts +93 -0
  164. package/dist/types/data-display.js +1 -0
  165. package/dist/types/feedback.d.ts +92 -0
  166. package/dist/types/feedback.js +1 -0
  167. package/dist/types/index.d.ts +4 -0
  168. package/dist/types/layout.d.ts +57 -0
  169. package/dist/types/layout.js +1 -0
  170. package/dist/types/mobile.d.ts +91 -0
  171. package/dist/types/mobile.js +1 -0
  172. package/dist/utils/gestures.d.ts +219 -0
  173. package/dist/utils/gestures.js +492 -0
  174. package/dist/utils/haptics.d.ts +89 -0
  175. package/dist/utils/haptics.js +198 -0
  176. package/dist/utils/platform.d.ts +47 -0
  177. package/dist/utils/platform.js +156 -0
  178. package/package.json +1 -1
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Haptics Utility - Cross-platform haptic feedback wrapper
3
+ *
4
+ * Wraps Capacitor Haptics with graceful web fallback (no-op on web).
5
+ * Uses optional peer dependency pattern - works without @capacitor/haptics installed.
6
+ * All functions are async and never throw - errors are caught silently.
7
+ */
8
+ /**
9
+ * Triggers impact haptic feedback.
10
+ *
11
+ * @param style - Impact intensity: 'light', 'medium', or 'heavy'
12
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Light tap feedback
17
+ * await hapticImpact('light');
18
+ *
19
+ * // Heavy impact for important actions
20
+ * await hapticImpact('heavy');
21
+ * ```
22
+ */
23
+ export declare function hapticImpact(style: 'light' | 'medium' | 'heavy'): Promise<void>;
24
+ /**
25
+ * Triggers notification haptic feedback.
26
+ *
27
+ * @param type - Notification type: 'success', 'warning', or 'error'
28
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Success feedback after form submission
33
+ * await hapticNotification('success');
34
+ *
35
+ * // Warning feedback for validation issues
36
+ * await hapticNotification('warning');
37
+ *
38
+ * // Error feedback for failures
39
+ * await hapticNotification('error');
40
+ * ```
41
+ */
42
+ export declare function hapticNotification(type: 'success' | 'warning' | 'error'): Promise<void>;
43
+ /**
44
+ * Triggers selection change haptic feedback.
45
+ * Use this for UI selection changes like picker scrolling or toggle switches.
46
+ *
47
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // Feedback when user changes selection
52
+ * function onSelectionChange(value: string) {
53
+ * await hapticSelection();
54
+ * setSelected(value);
55
+ * }
56
+ * ```
57
+ */
58
+ export declare function hapticSelection(): Promise<void>;
59
+ /**
60
+ * Triggers a simple vibration.
61
+ *
62
+ * @param duration - Vibration duration in milliseconds (default: 300ms)
63
+ * @returns Promise that resolves when vibration is complete (or immediately on web)
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * // Default vibration
68
+ * await hapticVibrate();
69
+ *
70
+ * // Custom duration vibration
71
+ * await hapticVibrate(500);
72
+ * ```
73
+ */
74
+ export declare function hapticVibrate(duration?: number): Promise<void>;
75
+ /**
76
+ * Checks if haptics are available on the current platform.
77
+ * Useful for conditional UI that depends on haptic support.
78
+ *
79
+ * @returns Promise<boolean> - true if haptics are available
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const hasHaptics = await isHapticsAvailable();
84
+ * if (hasHaptics) {
85
+ * showHapticSettings();
86
+ * }
87
+ * ```
88
+ */
89
+ export declare function isHapticsAvailable(): Promise<boolean>;
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Haptics Utility - Cross-platform haptic feedback wrapper
3
+ *
4
+ * Wraps Capacitor Haptics with graceful web fallback (no-op on web).
5
+ * Uses optional peer dependency pattern - works without @capacitor/haptics installed.
6
+ * All functions are async and never throw - errors are caught silently.
7
+ */
8
+ // Cached Haptics module reference
9
+ let hapticsModule = null;
10
+ let hapticsLoaded = false;
11
+ let hapticsAvailable = false;
12
+ /**
13
+ * Checks if we're running in a Capacitor native environment
14
+ */
15
+ function isCapacitorNative() {
16
+ if (typeof window === 'undefined')
17
+ return false;
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const cap = window.Capacitor;
20
+ return cap?.isNativePlatform?.() ?? false;
21
+ }
22
+ /**
23
+ * Attempts to load the Capacitor Haptics module.
24
+ * Only attempts import in Capacitor native environment to avoid Vite build errors.
25
+ * Caches the result to avoid repeated dynamic imports.
26
+ */
27
+ async function getHaptics() {
28
+ if (hapticsLoaded) {
29
+ return hapticsModule;
30
+ }
31
+ // Only attempt to load haptics in native Capacitor environment
32
+ if (!isCapacitorNative()) {
33
+ hapticsLoaded = true;
34
+ hapticsModule = null;
35
+ hapticsAvailable = false;
36
+ return null;
37
+ }
38
+ try {
39
+ // Dynamic import with variable to prevent Vite static analysis
40
+ const modulePath = '@capacitor/haptics';
41
+ const module = await import(/* @vite-ignore */ modulePath);
42
+ hapticsModule = module.Haptics;
43
+ hapticsAvailable = true;
44
+ }
45
+ catch {
46
+ // @capacitor/haptics not installed or import failed
47
+ hapticsModule = null;
48
+ hapticsAvailable = false;
49
+ }
50
+ hapticsLoaded = true;
51
+ return hapticsModule;
52
+ }
53
+ /**
54
+ * Style mapping from simple strings to Capacitor ImpactStyle values
55
+ */
56
+ const impactStyleMap = {
57
+ light: 'Light',
58
+ medium: 'Medium',
59
+ heavy: 'Heavy'
60
+ };
61
+ /**
62
+ * Type mapping from simple strings to Capacitor NotificationType values
63
+ */
64
+ const notificationTypeMap = {
65
+ success: 'Success',
66
+ warning: 'Warning',
67
+ error: 'Error'
68
+ };
69
+ /**
70
+ * Triggers impact haptic feedback.
71
+ *
72
+ * @param style - Impact intensity: 'light', 'medium', or 'heavy'
73
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * // Light tap feedback
78
+ * await hapticImpact('light');
79
+ *
80
+ * // Heavy impact for important actions
81
+ * await hapticImpact('heavy');
82
+ * ```
83
+ */
84
+ export async function hapticImpact(style) {
85
+ try {
86
+ const haptics = await getHaptics();
87
+ if (haptics) {
88
+ await haptics.impact({ style: impactStyleMap[style] });
89
+ }
90
+ }
91
+ catch {
92
+ // Silently ignore errors - haptics should never break functionality
93
+ }
94
+ }
95
+ /**
96
+ * Triggers notification haptic feedback.
97
+ *
98
+ * @param type - Notification type: 'success', 'warning', or 'error'
99
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * // Success feedback after form submission
104
+ * await hapticNotification('success');
105
+ *
106
+ * // Warning feedback for validation issues
107
+ * await hapticNotification('warning');
108
+ *
109
+ * // Error feedback for failures
110
+ * await hapticNotification('error');
111
+ * ```
112
+ */
113
+ export async function hapticNotification(type) {
114
+ try {
115
+ const haptics = await getHaptics();
116
+ if (haptics) {
117
+ await haptics.notification({ type: notificationTypeMap[type] });
118
+ }
119
+ }
120
+ catch {
121
+ // Silently ignore errors - haptics should never break functionality
122
+ }
123
+ }
124
+ /**
125
+ * Triggers selection change haptic feedback.
126
+ * Use this for UI selection changes like picker scrolling or toggle switches.
127
+ *
128
+ * @returns Promise that resolves when haptic is complete (or immediately on web)
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * // Feedback when user changes selection
133
+ * function onSelectionChange(value: string) {
134
+ * await hapticSelection();
135
+ * setSelected(value);
136
+ * }
137
+ * ```
138
+ */
139
+ export async function hapticSelection() {
140
+ try {
141
+ const haptics = await getHaptics();
142
+ if (haptics) {
143
+ await haptics.selectionChanged();
144
+ }
145
+ }
146
+ catch {
147
+ // Silently ignore errors - haptics should never break functionality
148
+ }
149
+ }
150
+ /**
151
+ * Triggers a simple vibration.
152
+ *
153
+ * @param duration - Vibration duration in milliseconds (default: 300ms)
154
+ * @returns Promise that resolves when vibration is complete (or immediately on web)
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * // Default vibration
159
+ * await hapticVibrate();
160
+ *
161
+ * // Custom duration vibration
162
+ * await hapticVibrate(500);
163
+ * ```
164
+ */
165
+ export async function hapticVibrate(duration = 300) {
166
+ try {
167
+ const haptics = await getHaptics();
168
+ if (haptics) {
169
+ await haptics.vibrate({ duration });
170
+ }
171
+ }
172
+ catch {
173
+ // Silently ignore errors - haptics should never break functionality
174
+ }
175
+ }
176
+ /**
177
+ * Checks if haptics are available on the current platform.
178
+ * Useful for conditional UI that depends on haptic support.
179
+ *
180
+ * @returns Promise<boolean> - true if haptics are available
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const hasHaptics = await isHapticsAvailable();
185
+ * if (hasHaptics) {
186
+ * showHapticSettings();
187
+ * }
188
+ * ```
189
+ */
190
+ export async function isHapticsAvailable() {
191
+ try {
192
+ await getHaptics();
193
+ return hapticsAvailable;
194
+ }
195
+ catch {
196
+ return false;
197
+ }
198
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Platform Detection Utility
3
+ * Detects the current platform (iOS, Android, or Web) using Capacitor when available.
4
+ * Provides graceful fallback when Capacitor is not installed or not running in a native context.
5
+ */
6
+ /**
7
+ * Supported platform types
8
+ */
9
+ export type Platform = 'ios' | 'android' | 'web';
10
+ /**
11
+ * Initialize platform detection asynchronously
12
+ * Call this early in your app lifecycle for most accurate detection
13
+ * @returns Promise that resolves when platform is detected
14
+ */
15
+ export declare function initPlatform(): Promise<Platform>;
16
+ /**
17
+ * Get the current platform
18
+ * Returns immediately with best available detection (may use sync fallback)
19
+ * For guaranteed accuracy, call initPlatform() first and await it
20
+ * @returns The detected platform
21
+ */
22
+ export declare function getPlatform(): Platform;
23
+ /**
24
+ * Check if running on iOS
25
+ * @returns true if the current platform is iOS
26
+ */
27
+ export declare function isIOS(): boolean;
28
+ /**
29
+ * Check if running on Android
30
+ * @returns true if the current platform is Android
31
+ */
32
+ export declare function isAndroid(): boolean;
33
+ /**
34
+ * Check if running as a native app (iOS or Android)
35
+ * @returns true if running in a native Capacitor context
36
+ */
37
+ export declare function isNative(): boolean;
38
+ /**
39
+ * Check if running on web (browser without native wrapper)
40
+ * @returns true if running in a standard web browser
41
+ */
42
+ export declare function isWeb(): boolean;
43
+ /**
44
+ * Reset platform detection (useful for testing)
45
+ * @internal
46
+ */
47
+ export declare function _resetPlatform(): void;
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Platform Detection Utility
3
+ * Detects the current platform (iOS, Android, or Web) using Capacitor when available.
4
+ * Provides graceful fallback when Capacitor is not installed or not running in a native context.
5
+ */
6
+ /**
7
+ * Internal state - initialized lazily on first access
8
+ */
9
+ let _platform = 'web';
10
+ let _initialized = false;
11
+ /**
12
+ * Initialize platform detection
13
+ * Uses dynamic import to gracefully handle cases where @capacitor/core is not installed
14
+ */
15
+ async function initializePlatform() {
16
+ if (_initialized)
17
+ return;
18
+ try {
19
+ // Dynamic import to handle cases where Capacitor is not installed
20
+ const capacitorModule = (await import('@capacitor/core'));
21
+ const Capacitor = capacitorModule.Capacitor;
22
+ if (Capacitor && typeof Capacitor.getPlatform === 'function') {
23
+ const detectedPlatform = Capacitor.getPlatform();
24
+ if (detectedPlatform === 'ios' ||
25
+ detectedPlatform === 'android' ||
26
+ detectedPlatform === 'web') {
27
+ _platform = detectedPlatform;
28
+ }
29
+ }
30
+ }
31
+ catch {
32
+ // Capacitor not available - default to 'web'
33
+ _platform = 'web';
34
+ }
35
+ _initialized = true;
36
+ }
37
+ /**
38
+ * Synchronous platform detection using user agent as fallback
39
+ * This is used for immediate platform detection without async initialization
40
+ */
41
+ function detectPlatformSync() {
42
+ if (_initialized)
43
+ return _platform;
44
+ // Check if running in browser environment
45
+ if (typeof window === 'undefined' || typeof navigator === 'undefined') {
46
+ return 'web';
47
+ }
48
+ // Try synchronous Capacitor detection first
49
+ try {
50
+ // Check for Capacitor global (may be available if loaded synchronously)
51
+ const win = window;
52
+ if (win.Capacitor && typeof win.Capacitor.getPlatform === 'function') {
53
+ const detectedPlatform = win.Capacitor.getPlatform();
54
+ if (detectedPlatform === 'ios' ||
55
+ detectedPlatform === 'android' ||
56
+ detectedPlatform === 'web') {
57
+ _platform = detectedPlatform;
58
+ _initialized = true;
59
+ return _platform;
60
+ }
61
+ }
62
+ }
63
+ catch {
64
+ // Capacitor not available synchronously
65
+ }
66
+ // Fallback to user agent detection for native webviews
67
+ const userAgent = navigator.userAgent.toLowerCase();
68
+ // Check for iOS (iPhone, iPad, iPod)
69
+ if (/iphone|ipad|ipod/.test(userAgent)) {
70
+ // Additional check for native iOS app context
71
+ const isNativeIOS = /capacitor|ionic|cordova/.test(userAgent) ||
72
+ window.webkit?.messageHandlers !==
73
+ undefined;
74
+ if (isNativeIOS) {
75
+ _platform = 'ios';
76
+ _initialized = true;
77
+ return _platform;
78
+ }
79
+ }
80
+ // Check for Android
81
+ if (/android/.test(userAgent)) {
82
+ // Additional check for native Android app context
83
+ const isNativeAndroid = /capacitor|ionic|cordova/.test(userAgent) ||
84
+ window.AndroidBridge !== undefined;
85
+ if (isNativeAndroid) {
86
+ _platform = 'android';
87
+ _initialized = true;
88
+ return _platform;
89
+ }
90
+ }
91
+ // Default to web
92
+ _platform = 'web';
93
+ _initialized = true;
94
+ return _platform;
95
+ }
96
+ /**
97
+ * Initialize platform detection asynchronously
98
+ * Call this early in your app lifecycle for most accurate detection
99
+ * @returns Promise that resolves when platform is detected
100
+ */
101
+ export async function initPlatform() {
102
+ await initializePlatform();
103
+ return _platform;
104
+ }
105
+ /**
106
+ * Get the current platform
107
+ * Returns immediately with best available detection (may use sync fallback)
108
+ * For guaranteed accuracy, call initPlatform() first and await it
109
+ * @returns The detected platform
110
+ */
111
+ export function getPlatform() {
112
+ if (!_initialized) {
113
+ // Use sync detection for immediate response
114
+ detectPlatformSync();
115
+ // Also kick off async detection for future calls
116
+ initializePlatform();
117
+ }
118
+ return _platform;
119
+ }
120
+ /**
121
+ * Check if running on iOS
122
+ * @returns true if the current platform is iOS
123
+ */
124
+ export function isIOS() {
125
+ return getPlatform() === 'ios';
126
+ }
127
+ /**
128
+ * Check if running on Android
129
+ * @returns true if the current platform is Android
130
+ */
131
+ export function isAndroid() {
132
+ return getPlatform() === 'android';
133
+ }
134
+ /**
135
+ * Check if running as a native app (iOS or Android)
136
+ * @returns true if running in a native Capacitor context
137
+ */
138
+ export function isNative() {
139
+ const platform = getPlatform();
140
+ return platform === 'ios' || platform === 'android';
141
+ }
142
+ /**
143
+ * Check if running on web (browser without native wrapper)
144
+ * @returns true if running in a standard web browser
145
+ */
146
+ export function isWeb() {
147
+ return getPlatform() === 'web';
148
+ }
149
+ /**
150
+ * Reset platform detection (useful for testing)
151
+ * @internal
152
+ */
153
+ export function _resetPlatform() {
154
+ _platform = 'web';
155
+ _initialized = false;
156
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspect-ops/exon-ui",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Reusable Svelte UI components for web and Capacitor mobile apps",
5
5
  "author": "Exon Team",
6
6
  "license": "MIT",