@mobileai/react-native 0.9.17 → 0.9.18

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 (213) hide show
  1. package/package.json +2 -5
  2. package/lib/module/__cli_tmp__.js.map +0 -1
  3. package/lib/module/components/AIAgent.js.map +0 -1
  4. package/lib/module/components/AIZone.js.map +0 -1
  5. package/lib/module/components/AgentChatBar.js.map +0 -1
  6. package/lib/module/components/AgentErrorBoundary.js.map +0 -1
  7. package/lib/module/components/AgentOverlay.js.map +0 -1
  8. package/lib/module/components/DiscoveryTooltip.js.map +0 -1
  9. package/lib/module/components/HighlightOverlay.js.map +0 -1
  10. package/lib/module/components/Icons.js.map +0 -1
  11. package/lib/module/components/ProactiveHint.js.map +0 -1
  12. package/lib/module/components/cards/InfoCard.js.map +0 -1
  13. package/lib/module/components/cards/ReviewSummary.js.map +0 -1
  14. package/lib/module/config/endpoints.js.map +0 -1
  15. package/lib/module/core/ActionRegistry.js.map +0 -1
  16. package/lib/module/core/AgentRuntime.js.map +0 -1
  17. package/lib/module/core/FiberTreeWalker.js.map +0 -1
  18. package/lib/module/core/IdleDetector.js.map +0 -1
  19. package/lib/module/core/MCPBridge.js.map +0 -1
  20. package/lib/module/core/ScreenDehydrator.js.map +0 -1
  21. package/lib/module/core/ZoneRegistry.js.map +0 -1
  22. package/lib/module/core/systemPrompt.js.map +0 -1
  23. package/lib/module/core/types.js.map +0 -1
  24. package/lib/module/hooks/useAction.js.map +0 -1
  25. package/lib/module/index.js.map +0 -1
  26. package/lib/module/plugin/withAppIntents.js.map +0 -1
  27. package/lib/module/providers/GeminiProvider.js.map +0 -1
  28. package/lib/module/providers/OpenAIProvider.js.map +0 -1
  29. package/lib/module/providers/ProviderFactory.js.map +0 -1
  30. package/lib/module/services/AudioInputService.js.map +0 -1
  31. package/lib/module/services/AudioOutputService.js.map +0 -1
  32. package/lib/module/services/KnowledgeBaseService.js.map +0 -1
  33. package/lib/module/services/VoiceService.js.map +0 -1
  34. package/lib/module/services/flags/FlagService.js.map +0 -1
  35. package/lib/module/services/telemetry/MobileAI.js.map +0 -1
  36. package/lib/module/services/telemetry/PiiScrubber.js.map +0 -1
  37. package/lib/module/services/telemetry/TelemetryService.js.map +0 -1
  38. package/lib/module/services/telemetry/TouchAutoCapture.js.map +0 -1
  39. package/lib/module/services/telemetry/device.js.map +0 -1
  40. package/lib/module/services/telemetry/deviceMetadata.js.map +0 -1
  41. package/lib/module/services/telemetry/index.js.map +0 -1
  42. package/lib/module/services/telemetry/types.js.map +0 -1
  43. package/lib/module/support/CSATSurvey.js.map +0 -1
  44. package/lib/module/support/EscalationEventSource.js.map +0 -1
  45. package/lib/module/support/EscalationSocket.js.map +0 -1
  46. package/lib/module/support/SupportChatModal.js.map +0 -1
  47. package/lib/module/support/SupportGreeting.js.map +0 -1
  48. package/lib/module/support/TicketStore.js.map +0 -1
  49. package/lib/module/support/escalateTool.js.map +0 -1
  50. package/lib/module/support/index.js.map +0 -1
  51. package/lib/module/support/supportPrompt.js.map +0 -1
  52. package/lib/module/support/types.js.map +0 -1
  53. package/lib/module/tools/datePickerTool.js.map +0 -1
  54. package/lib/module/tools/guideTool.js.map +0 -1
  55. package/lib/module/tools/index.js.map +0 -1
  56. package/lib/module/tools/keyboardTool.js.map +0 -1
  57. package/lib/module/tools/longPressTool.js.map +0 -1
  58. package/lib/module/tools/pickerTool.js.map +0 -1
  59. package/lib/module/tools/restoreTool.js.map +0 -1
  60. package/lib/module/tools/scrollTool.js.map +0 -1
  61. package/lib/module/tools/simplifyTool.js.map +0 -1
  62. package/lib/module/tools/sliderTool.js.map +0 -1
  63. package/lib/module/tools/tapTool.js.map +0 -1
  64. package/lib/module/tools/typeTool.js.map +0 -1
  65. package/lib/module/tools/types.js.map +0 -1
  66. package/lib/module/types/jsx.d.js.map +0 -1
  67. package/lib/module/utils/audioUtils.js.map +0 -1
  68. package/lib/module/utils/logger.js.map +0 -1
  69. package/lib/typescript/babel.config.d.ts.map +0 -1
  70. package/lib/typescript/bin/generate-map.d.cts.map +0 -1
  71. package/lib/typescript/eslint.config.d.mts.map +0 -1
  72. package/lib/typescript/generate-map.d.ts.map +0 -1
  73. package/lib/typescript/src/__cli_tmp__.d.ts.map +0 -1
  74. package/lib/typescript/src/components/AIAgent.d.ts.map +0 -1
  75. package/lib/typescript/src/components/AIZone.d.ts.map +0 -1
  76. package/lib/typescript/src/components/AgentChatBar.d.ts.map +0 -1
  77. package/lib/typescript/src/components/AgentErrorBoundary.d.ts.map +0 -1
  78. package/lib/typescript/src/components/AgentOverlay.d.ts.map +0 -1
  79. package/lib/typescript/src/components/DiscoveryTooltip.d.ts.map +0 -1
  80. package/lib/typescript/src/components/HighlightOverlay.d.ts.map +0 -1
  81. package/lib/typescript/src/components/Icons.d.ts.map +0 -1
  82. package/lib/typescript/src/components/ProactiveHint.d.ts.map +0 -1
  83. package/lib/typescript/src/components/cards/InfoCard.d.ts.map +0 -1
  84. package/lib/typescript/src/components/cards/ReviewSummary.d.ts.map +0 -1
  85. package/lib/typescript/src/config/endpoints.d.ts.map +0 -1
  86. package/lib/typescript/src/core/ActionRegistry.d.ts.map +0 -1
  87. package/lib/typescript/src/core/AgentRuntime.d.ts.map +0 -1
  88. package/lib/typescript/src/core/FiberTreeWalker.d.ts.map +0 -1
  89. package/lib/typescript/src/core/IdleDetector.d.ts.map +0 -1
  90. package/lib/typescript/src/core/MCPBridge.d.ts.map +0 -1
  91. package/lib/typescript/src/core/ScreenDehydrator.d.ts.map +0 -1
  92. package/lib/typescript/src/core/ZoneRegistry.d.ts.map +0 -1
  93. package/lib/typescript/src/core/systemPrompt.d.ts.map +0 -1
  94. package/lib/typescript/src/core/types.d.ts.map +0 -1
  95. package/lib/typescript/src/hooks/useAction.d.ts.map +0 -1
  96. package/lib/typescript/src/index.d.ts.map +0 -1
  97. package/lib/typescript/src/plugin/withAppIntents.d.ts.map +0 -1
  98. package/lib/typescript/src/providers/GeminiProvider.d.ts.map +0 -1
  99. package/lib/typescript/src/providers/OpenAIProvider.d.ts.map +0 -1
  100. package/lib/typescript/src/providers/ProviderFactory.d.ts.map +0 -1
  101. package/lib/typescript/src/services/AudioInputService.d.ts.map +0 -1
  102. package/lib/typescript/src/services/AudioOutputService.d.ts.map +0 -1
  103. package/lib/typescript/src/services/KnowledgeBaseService.d.ts.map +0 -1
  104. package/lib/typescript/src/services/VoiceService.d.ts.map +0 -1
  105. package/lib/typescript/src/services/flags/FlagService.d.ts.map +0 -1
  106. package/lib/typescript/src/services/telemetry/MobileAI.d.ts.map +0 -1
  107. package/lib/typescript/src/services/telemetry/PiiScrubber.d.ts.map +0 -1
  108. package/lib/typescript/src/services/telemetry/TelemetryService.d.ts.map +0 -1
  109. package/lib/typescript/src/services/telemetry/TouchAutoCapture.d.ts.map +0 -1
  110. package/lib/typescript/src/services/telemetry/device.d.ts.map +0 -1
  111. package/lib/typescript/src/services/telemetry/deviceMetadata.d.ts.map +0 -1
  112. package/lib/typescript/src/services/telemetry/index.d.ts.map +0 -1
  113. package/lib/typescript/src/services/telemetry/types.d.ts.map +0 -1
  114. package/lib/typescript/src/support/CSATSurvey.d.ts.map +0 -1
  115. package/lib/typescript/src/support/EscalationEventSource.d.ts.map +0 -1
  116. package/lib/typescript/src/support/EscalationSocket.d.ts.map +0 -1
  117. package/lib/typescript/src/support/SupportChatModal.d.ts.map +0 -1
  118. package/lib/typescript/src/support/SupportGreeting.d.ts.map +0 -1
  119. package/lib/typescript/src/support/TicketStore.d.ts.map +0 -1
  120. package/lib/typescript/src/support/escalateTool.d.ts.map +0 -1
  121. package/lib/typescript/src/support/index.d.ts.map +0 -1
  122. package/lib/typescript/src/support/supportPrompt.d.ts.map +0 -1
  123. package/lib/typescript/src/support/types.d.ts.map +0 -1
  124. package/lib/typescript/src/tools/datePickerTool.d.ts.map +0 -1
  125. package/lib/typescript/src/tools/guideTool.d.ts.map +0 -1
  126. package/lib/typescript/src/tools/index.d.ts.map +0 -1
  127. package/lib/typescript/src/tools/keyboardTool.d.ts.map +0 -1
  128. package/lib/typescript/src/tools/longPressTool.d.ts.map +0 -1
  129. package/lib/typescript/src/tools/pickerTool.d.ts.map +0 -1
  130. package/lib/typescript/src/tools/restoreTool.d.ts.map +0 -1
  131. package/lib/typescript/src/tools/scrollTool.d.ts.map +0 -1
  132. package/lib/typescript/src/tools/simplifyTool.d.ts.map +0 -1
  133. package/lib/typescript/src/tools/sliderTool.d.ts.map +0 -1
  134. package/lib/typescript/src/tools/tapTool.d.ts.map +0 -1
  135. package/lib/typescript/src/tools/typeTool.d.ts.map +0 -1
  136. package/lib/typescript/src/tools/types.d.ts.map +0 -1
  137. package/lib/typescript/src/utils/audioUtils.d.ts.map +0 -1
  138. package/lib/typescript/src/utils/logger.d.ts.map +0 -1
  139. package/src/__cli_tmp__.tsx +0 -9
  140. package/src/cli/analyzers/chain-analyzer.ts +0 -183
  141. package/src/cli/extractors/ai-extractor.ts +0 -6
  142. package/src/cli/extractors/ast-extractor.ts +0 -551
  143. package/src/cli/generate-intents.ts +0 -140
  144. package/src/cli/generate-map.ts +0 -121
  145. package/src/cli/generate-swift.ts +0 -116
  146. package/src/cli/scanners/expo-scanner.ts +0 -203
  147. package/src/cli/scanners/rn-scanner.ts +0 -445
  148. package/src/components/AIAgent.tsx +0 -1716
  149. package/src/components/AIZone.tsx +0 -147
  150. package/src/components/AgentChatBar.tsx +0 -1143
  151. package/src/components/AgentErrorBoundary.tsx +0 -78
  152. package/src/components/AgentOverlay.tsx +0 -73
  153. package/src/components/DiscoveryTooltip.tsx +0 -148
  154. package/src/components/HighlightOverlay.tsx +0 -136
  155. package/src/components/Icons.tsx +0 -253
  156. package/src/components/ProactiveHint.tsx +0 -145
  157. package/src/components/cards/InfoCard.tsx +0 -58
  158. package/src/components/cards/ReviewSummary.tsx +0 -76
  159. package/src/config/endpoints.ts +0 -22
  160. package/src/core/ActionRegistry.ts +0 -105
  161. package/src/core/AgentRuntime.ts +0 -1471
  162. package/src/core/FiberTreeWalker.ts +0 -930
  163. package/src/core/IdleDetector.ts +0 -72
  164. package/src/core/MCPBridge.ts +0 -163
  165. package/src/core/ScreenDehydrator.ts +0 -53
  166. package/src/core/ZoneRegistry.ts +0 -44
  167. package/src/core/systemPrompt.ts +0 -431
  168. package/src/core/types.ts +0 -521
  169. package/src/hooks/useAction.ts +0 -182
  170. package/src/index.ts +0 -83
  171. package/src/plugin/withAppIntents.ts +0 -98
  172. package/src/providers/GeminiProvider.ts +0 -357
  173. package/src/providers/OpenAIProvider.ts +0 -379
  174. package/src/providers/ProviderFactory.ts +0 -36
  175. package/src/services/AudioInputService.ts +0 -226
  176. package/src/services/AudioOutputService.ts +0 -236
  177. package/src/services/KnowledgeBaseService.ts +0 -156
  178. package/src/services/VoiceService.ts +0 -451
  179. package/src/services/flags/FlagService.ts +0 -137
  180. package/src/services/telemetry/MobileAI.ts +0 -66
  181. package/src/services/telemetry/PiiScrubber.ts +0 -17
  182. package/src/services/telemetry/TelemetryService.ts +0 -323
  183. package/src/services/telemetry/TouchAutoCapture.ts +0 -165
  184. package/src/services/telemetry/device.ts +0 -93
  185. package/src/services/telemetry/deviceMetadata.ts +0 -13
  186. package/src/services/telemetry/index.ts +0 -13
  187. package/src/services/telemetry/types.ts +0 -75
  188. package/src/support/CSATSurvey.tsx +0 -304
  189. package/src/support/EscalationEventSource.ts +0 -190
  190. package/src/support/EscalationSocket.ts +0 -152
  191. package/src/support/SupportChatModal.tsx +0 -563
  192. package/src/support/SupportGreeting.tsx +0 -161
  193. package/src/support/TicketStore.ts +0 -100
  194. package/src/support/escalateTool.ts +0 -174
  195. package/src/support/index.ts +0 -29
  196. package/src/support/supportPrompt.ts +0 -55
  197. package/src/support/types.ts +0 -155
  198. package/src/tools/datePickerTool.ts +0 -60
  199. package/src/tools/guideTool.ts +0 -76
  200. package/src/tools/index.ts +0 -20
  201. package/src/tools/keyboardTool.ts +0 -30
  202. package/src/tools/longPressTool.ts +0 -61
  203. package/src/tools/pickerTool.ts +0 -115
  204. package/src/tools/restoreTool.ts +0 -33
  205. package/src/tools/scrollTool.ts +0 -156
  206. package/src/tools/simplifyTool.ts +0 -33
  207. package/src/tools/sliderTool.ts +0 -65
  208. package/src/tools/tapTool.ts +0 -93
  209. package/src/tools/typeTool.ts +0 -113
  210. package/src/tools/types.ts +0 -58
  211. package/src/types/jsx.d.ts +0 -20
  212. package/src/utils/audioUtils.ts +0 -54
  213. package/src/utils/logger.ts +0 -38
@@ -1,78 +0,0 @@
1
- /**
2
- * AgentErrorBoundary — Catches React rendering errors caused by AI agent actions.
3
- *
4
- * When the AI taps, scrolls, or navigates, the action itself may succeed
5
- * but trigger async side-effects (useEffect, onViewableItemsChanged) that
6
- * crash during the next React render cycle. This boundary catches those
7
- * errors, preventing red screen crashes and auto-recovering the UI.
8
- *
9
- * Recovery strategy:
10
- * 1. Catch the error via getDerivedStateFromError
11
- * 2. Log it and report to agent runtime via onError callback
12
- * 3. Auto-reset after a brief delay — remounts children cleanly
13
- */
14
-
15
- import React from 'react';
16
- import { logger } from '../utils/logger';
17
-
18
- interface Props {
19
- children: React.ReactNode;
20
- /** Called when an error is caught — reports back to agent runtime */
21
- onError?: (error: Error, componentStack?: string) => void;
22
- telemetryRef?: React.RefObject<any>; // Using any to avoid circular import, we duck-type track()
23
- }
24
-
25
- interface State {
26
- hasError: boolean;
27
- }
28
-
29
- export class AgentErrorBoundary extends React.Component<Props, State> {
30
- state: State = { hasError: false };
31
- private resetTimer: ReturnType<typeof setTimeout> | null = null;
32
-
33
- static getDerivedStateFromError(_error: Error): State {
34
- return { hasError: true };
35
- }
36
-
37
- componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
38
- const componentStack = errorInfo?.componentStack || '';
39
- logger.warn(
40
- 'AgentErrorBoundary',
41
- `🛡️ Caught rendering error: ${error.message}\n${componentStack}`
42
- );
43
- this.props.onError?.(error, componentStack);
44
-
45
- // Track the render error silently in analytics
46
- if (this.props.telemetryRef?.current?.track) {
47
- this.props.telemetryRef.current.track('render_error', {
48
- message: error.message,
49
- component: componentStack?.split('\n')[1]?.trim() ?? 'unknown',
50
- screen: this.props.telemetryRef.current.screen,
51
- });
52
- }
53
- }
54
-
55
- componentDidUpdate(_prevProps: Props, prevState: State): void {
56
- // Auto-recover: reset error state after brief delay to remount children
57
- if (this.state.hasError && !prevState.hasError) {
58
- this.resetTimer = setTimeout(() => {
59
- this.setState({ hasError: false });
60
- }, 50);
61
- }
62
- }
63
-
64
- componentWillUnmount(): void {
65
- if (this.resetTimer) {
66
- clearTimeout(this.resetTimer);
67
- }
68
- }
69
-
70
- render(): React.ReactNode {
71
- if (this.state.hasError) {
72
- // Return null briefly — children will remount on next tick
73
- // when hasError resets to false via componentDidUpdate
74
- return null;
75
- }
76
- return this.props.children;
77
- }
78
- }
@@ -1,73 +0,0 @@
1
- /**
2
- * AgentOverlay — Subtle thinking indicator shown while the AI agent is processing.
3
- * Includes a cancel button to stop the agent mid-execution.
4
- */
5
-
6
- import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native';
7
- import { CloseIcon } from './Icons';
8
-
9
- interface AgentOverlayProps {
10
- visible: boolean;
11
- statusText: string;
12
- onCancel?: () => void;
13
- }
14
-
15
- export function AgentOverlay({ visible, statusText, onCancel }: AgentOverlayProps) {
16
- if (!visible) return null;
17
-
18
- return (
19
- <View style={styles.overlay} pointerEvents="box-none">
20
- <View style={styles.pill}>
21
- <ActivityIndicator size="small" color="#fff" />
22
- <Text style={styles.text}>{statusText || 'Thinking...'}</Text>
23
- {onCancel && (
24
- <TouchableOpacity
25
- onPress={onCancel}
26
- style={styles.cancelButton}
27
- hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
28
- >
29
- <CloseIcon size={12} color="#fff" />
30
- </TouchableOpacity>
31
- )}
32
- </View>
33
- </View>
34
- );
35
- }
36
-
37
- const styles = StyleSheet.create({
38
- overlay: {
39
- position: 'absolute',
40
- top: 60,
41
- left: 0,
42
- right: 0,
43
- alignItems: 'center',
44
- zIndex: 9999,
45
- },
46
- pill: {
47
- flexDirection: 'row',
48
- alignItems: 'center',
49
- gap: 8,
50
- backgroundColor: 'rgba(26, 26, 46, 0.9)',
51
- paddingHorizontal: 16,
52
- paddingVertical: 10,
53
- borderRadius: 20,
54
- maxWidth: '85%',
55
- },
56
- text: {
57
- color: '#fff',
58
- fontSize: 14,
59
- fontWeight: '500',
60
- flexShrink: 1,
61
- },
62
- cancelButton: {
63
- marginLeft: 4,
64
- width: 22,
65
- height: 22,
66
- borderRadius: 11,
67
- backgroundColor: 'rgba(255, 255, 255, 0.2)',
68
- alignItems: 'center',
69
- justifyContent: 'center',
70
- flexShrink: 0,
71
- },
72
- });
73
-
@@ -1,148 +0,0 @@
1
- /**
2
- * DiscoveryTooltip — One-time tooltip shown above the FAB on first use.
3
- *
4
- * Tells users the AI can navigate the app and do things for them.
5
- * Shows once, then persists dismissal via AsyncStorage.
6
- * Bilingual: EN/AR.
7
- */
8
-
9
- import { useEffect, useRef } from 'react';
10
- import {
11
- View,
12
- Text,
13
- Pressable,
14
- StyleSheet,
15
- Animated,
16
- } from 'react-native';
17
-
18
- interface DiscoveryTooltipProps {
19
- language: 'en' | 'ar';
20
- primaryColor?: string;
21
- onDismiss: () => void;
22
- }
23
-
24
- const LABELS = {
25
- en: '✨ I can help you navigate the app and do things for you!',
26
- ar: '✨ أقدر أساعدك تتنقل في التطبيق وأعمل حاجات بدالك!',
27
- };
28
-
29
- const AUTO_DISMISS_MS = 6000;
30
-
31
- export function DiscoveryTooltip({
32
- language,
33
- primaryColor,
34
- onDismiss,
35
- }: DiscoveryTooltipProps) {
36
- const scaleAnim = useRef(new Animated.Value(0)).current;
37
- const opacityAnim = useRef(new Animated.Value(0)).current;
38
-
39
- useEffect(() => {
40
- // Spring-in entry
41
- Animated.parallel([
42
- Animated.spring(scaleAnim, {
43
- toValue: 1,
44
- friction: 6,
45
- tension: 80,
46
- useNativeDriver: true,
47
- }),
48
- Animated.timing(opacityAnim, {
49
- toValue: 1,
50
- duration: 200,
51
- useNativeDriver: true,
52
- }),
53
- ]).start();
54
-
55
- // Auto-dismiss after timeout
56
- const timer = setTimeout(() => {
57
- dismissWithAnimation();
58
- }, AUTO_DISMISS_MS);
59
-
60
- return () => clearTimeout(timer);
61
- // eslint-disable-next-line react-hooks/exhaustive-deps
62
- }, []);
63
-
64
- const dismissWithAnimation = () => {
65
- Animated.parallel([
66
- Animated.timing(scaleAnim, {
67
- toValue: 0,
68
- duration: 200,
69
- useNativeDriver: true,
70
- }),
71
- Animated.timing(opacityAnim, {
72
- toValue: 0,
73
- duration: 200,
74
- useNativeDriver: true,
75
- }),
76
- ]).start(() => onDismiss());
77
- };
78
-
79
- const isArabic = language === 'ar';
80
- const bgColor = primaryColor || '#1a1a2e';
81
-
82
- return (
83
- <Animated.View
84
- style={[
85
- styles.container,
86
- {
87
- backgroundColor: bgColor,
88
- transform: [{ scale: scaleAnim }],
89
- opacity: opacityAnim,
90
- },
91
- ]}
92
- >
93
- <Pressable onPress={dismissWithAnimation} style={styles.contentArea}>
94
- <Text style={[styles.text, isArabic && styles.textRTL]}>
95
- {LABELS[language]}
96
- </Text>
97
- </Pressable>
98
-
99
- {/* Triangle pointer toward FAB */}
100
- <View style={[styles.pointer, { borderTopColor: bgColor }]} />
101
- </Animated.View>
102
- );
103
- }
104
-
105
- const styles = StyleSheet.create({
106
- container: {
107
- position: 'absolute',
108
- bottom: 70,
109
- right: -4,
110
- minWidth: 200,
111
- maxWidth: 260,
112
- borderRadius: 16,
113
- paddingHorizontal: 14,
114
- paddingVertical: 10,
115
- shadowColor: '#000',
116
- shadowOffset: { width: 0, height: 4 },
117
- shadowOpacity: 0.3,
118
- shadowRadius: 8,
119
- elevation: 6,
120
- },
121
- contentArea: {
122
- flexDirection: 'row',
123
- alignItems: 'center',
124
- },
125
- text: {
126
- color: '#ffffff',
127
- fontSize: 13,
128
- lineHeight: 19,
129
- fontWeight: '500',
130
- },
131
- textRTL: {
132
- textAlign: 'right',
133
- writingDirection: 'rtl',
134
- },
135
- pointer: {
136
- position: 'absolute',
137
- bottom: -8,
138
- right: 22,
139
- width: 0,
140
- height: 0,
141
- borderLeftWidth: 8,
142
- borderRightWidth: 8,
143
- borderTopWidth: 8,
144
- borderLeftColor: 'transparent',
145
- borderRightColor: 'transparent',
146
- borderTopColor: '#1a1a2e',
147
- },
148
- });
@@ -1,136 +0,0 @@
1
- import { useEffect, useState, useRef } from 'react';
2
- import { View, Text, StyleSheet, Animated, Pressable, DeviceEventEmitter } from 'react-native';
3
-
4
- export interface HighlightEventData {
5
- pageX: number;
6
- pageY: number;
7
- width: number;
8
- height: number;
9
- message: string;
10
- autoRemoveAfterMs?: number;
11
- }
12
-
13
- export function HighlightOverlay() {
14
- const [highlight, setHighlight] = useState<HighlightEventData | null>(null);
15
- const pulseAnim = useRef(new Animated.Value(1)).current;
16
- const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
17
-
18
- useEffect(() => {
19
- const sub = DeviceEventEmitter.addListener('MOBILE_AI_HIGHLIGHT', (data: HighlightEventData | null) => {
20
- if (timerRef.current) clearTimeout(timerRef.current);
21
-
22
- setHighlight(data);
23
-
24
- if (data) {
25
- // Start pulsing ring
26
- pulseAnim.setValue(1);
27
- Animated.loop(
28
- Animated.sequence([
29
- Animated.timing(pulseAnim, { toValue: 1.2, duration: 800, useNativeDriver: true }),
30
- Animated.timing(pulseAnim, { toValue: 1, duration: 800, useNativeDriver: true }),
31
- ])
32
- ).start();
33
-
34
- // Auto-dismiss
35
- const ms = data.autoRemoveAfterMs || 5000;
36
- timerRef.current = setTimeout(() => {
37
- setHighlight(null);
38
- }, ms);
39
- }
40
- });
41
-
42
- return () => sub.remove();
43
- }, [pulseAnim]);
44
-
45
- if (!highlight) return null;
46
-
47
- const { pageX, pageY, width, height, message } = highlight;
48
-
49
- // Calculate tooltip position (prefer top, fallback to bottom if too close to top edge)
50
- const isTooHigh = pageY < 60;
51
- const tooltipTop = isTooHigh ? pageY + height + 12 : pageY - 45;
52
-
53
- return (
54
- <View style={StyleSheet.absoluteFill} pointerEvents="box-none">
55
- {/* Invisible pressable to dismiss on tap anywhere */}
56
- <Pressable testID="highlight-close-zone" style={StyleSheet.absoluteFill} onPress={() => setHighlight(null)} />
57
-
58
- {/* The Animated Ring */}
59
- <Animated.View
60
- style={[
61
- styles.ring,
62
- {
63
- left: pageX - 4,
64
- top: pageY - 4,
65
- width: width + 8,
66
- height: height + 8,
67
- transform: [{ scale: pulseAnim }],
68
- }
69
- ]}
70
- pointerEvents="none"
71
- />
72
-
73
- {/* The Tooltip */}
74
- <View style={[styles.tooltip, { top: tooltipTop }]} pointerEvents="none">
75
- <Text style={styles.message}>{message}</Text>
76
- <View style={isTooHigh ? styles.arrowUp : styles.arrowDown} />
77
- </View>
78
- </View>
79
- );
80
- }
81
-
82
- const styles = StyleSheet.create({
83
- ring: {
84
- position: 'absolute',
85
- borderWidth: 3,
86
- borderColor: '#007AFF', // iOS blue
87
- borderRadius: 8,
88
- backgroundColor: 'rgba(0, 122, 255, 0.15)', // Very subtle fill
89
- },
90
- tooltip: {
91
- position: 'absolute',
92
- alignSelf: 'center',
93
- backgroundColor: '#007AFF',
94
- paddingHorizontal: 12,
95
- paddingVertical: 8,
96
- borderRadius: 8,
97
- maxWidth: '80%',
98
- shadowColor: '#000',
99
- shadowOpacity: 0.2,
100
- shadowOffset: { width: 0, height: 2 },
101
- shadowRadius: 4,
102
- elevation: 4,
103
- },
104
- message: {
105
- color: '#fff',
106
- fontSize: 14,
107
- fontWeight: 'bold',
108
- textAlign: 'center',
109
- },
110
- arrowDown: {
111
- position: 'absolute',
112
- bottom: -6,
113
- alignSelf: 'center',
114
- width: 0,
115
- height: 0,
116
- borderLeftWidth: 6,
117
- borderRightWidth: 6,
118
- borderTopWidth: 6,
119
- borderLeftColor: 'transparent',
120
- borderRightColor: 'transparent',
121
- borderTopColor: '#007AFF',
122
- },
123
- arrowUp: {
124
- position: 'absolute',
125
- top: -6,
126
- alignSelf: 'center',
127
- width: 0,
128
- height: 0,
129
- borderLeftWidth: 6,
130
- borderRightWidth: 6,
131
- borderBottomWidth: 6,
132
- borderLeftColor: 'transparent',
133
- borderRightColor: 'transparent',
134
- borderBottomColor: '#007AFF',
135
- }
136
- });
@@ -1,253 +0,0 @@
1
- /**
2
- * Icons — Zero-dependency, View-based icons for the AI Agent chat bar.
3
- *
4
- * Why not emoji? iOS Simulator 26+ has a bug where emoji renders as "?".
5
- * Why not Unicode symbols? They look obscure and unprofessional.
6
- * Why not icon libraries? This is a library — zero runtime dependencies.
7
- *
8
- * These icons are built purely from React Native View components,
9
- * rendering identically on every platform and screen size.
10
- */
11
-
12
- import { View } from 'react-native';
13
-
14
- // ─── Mic Icon (pill + stem + base) ────────────────────────────
15
-
16
- export function MicIcon({ size = 20, color = '#fff' }: { size?: number; color?: string }) {
17
- const pillW = size * 0.4;
18
- const pillH = size * 0.5;
19
- const stemW = size * 0.08;
20
- const stemH = size * 0.18;
21
- const baseW = size * 0.35;
22
- const arcW = size * 0.55;
23
- const arcH = size * 0.35;
24
- const arcBorder = size * 0.07;
25
-
26
- return (
27
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
28
- {/* Pill (mic head) */}
29
- <View style={{
30
- width: pillW,
31
- height: pillH,
32
- borderRadius: pillW / 2,
33
- backgroundColor: color,
34
- }} />
35
- {/* Arc (U-shape around mic) */}
36
- <View style={{
37
- width: arcW,
38
- height: arcH,
39
- borderBottomLeftRadius: arcW / 2,
40
- borderBottomRightRadius: arcW / 2,
41
- borderWidth: arcBorder,
42
- borderTopWidth: 0,
43
- borderColor: color,
44
- marginTop: -(pillH * 0.3),
45
- }} />
46
- {/* Stem */}
47
- <View style={{
48
- width: stemW,
49
- height: stemH,
50
- backgroundColor: color,
51
- marginTop: -1,
52
- }} />
53
- {/* Base */}
54
- <View style={{
55
- width: baseW,
56
- height: stemW,
57
- backgroundColor: color,
58
- borderRadius: stemW / 2,
59
- }} />
60
- </View>
61
- );
62
- }
63
-
64
- // ─── Speaker Icon (cone + sound waves) ────────────────────────
65
-
66
- export function SpeakerIcon({ size = 20, color = '#fff', muted = false }: { size?: number; color?: string; muted?: boolean }) {
67
- const bodyW = size * 0.25;
68
- const bodyH = size * 0.3;
69
- const coneW = size * 0.2;
70
-
71
- return (
72
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center', flexDirection: 'row' }}>
73
- {/* Speaker body (rectangle) */}
74
- <View style={{
75
- width: bodyW,
76
- height: bodyH,
77
- backgroundColor: color,
78
- borderRadius: size * 0.03,
79
- }} />
80
- {/* Speaker cone (triangle via borders) */}
81
- <View style={{
82
- width: 0,
83
- height: 0,
84
- borderTopWidth: size * 0.25,
85
- borderTopColor: 'transparent',
86
- borderBottomWidth: size * 0.25,
87
- borderBottomColor: 'transparent',
88
- borderLeftWidth: coneW,
89
- borderLeftColor: color,
90
- marginLeft: -1,
91
- }} />
92
- {muted ? (
93
- /* Mute slash */
94
- <View style={{
95
- position: 'absolute',
96
- width: size * 0.08,
97
- height: size * 0.8,
98
- backgroundColor: color,
99
- borderRadius: size * 0.04,
100
- transform: [{ rotate: '45deg' }],
101
- }} />
102
- ) : (
103
- /* Sound waves */
104
- <View style={{ marginLeft: size * 0.05 }}>
105
- <View style={{
106
- width: size * 0.15,
107
- height: size * 0.3,
108
- borderWidth: size * 0.05,
109
- borderColor: color,
110
- borderLeftWidth: 0,
111
- borderTopLeftRadius: 0,
112
- borderBottomLeftRadius: 0,
113
- borderTopRightRadius: size * 0.15,
114
- borderBottomRightRadius: size * 0.15,
115
- }} />
116
- </View>
117
- )}
118
- </View>
119
- );
120
- }
121
-
122
- // ─── Send Arrow (upward arrow) ────────────────────────────────
123
-
124
- export function SendArrowIcon({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
125
- // Filled right-pointing triangle (like iOS Messages send button)
126
- const triH = size * 0.55;
127
- return (
128
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
129
- <View style={{
130
- width: 0,
131
- height: 0,
132
- borderTopWidth: triH / 2,
133
- borderTopColor: 'transparent',
134
- borderBottomWidth: triH / 2,
135
- borderBottomColor: 'transparent',
136
- borderLeftWidth: triH * 0.85,
137
- borderLeftColor: color,
138
- marginLeft: size * 0.1,
139
- }} />
140
- </View>
141
- );
142
- }
143
-
144
- // ─── Stop Icon (filled square) ────────────────────────────────
145
-
146
- export function StopIcon({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
147
- const sq = size * 0.45;
148
- return (
149
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
150
- <View style={{
151
- width: sq,
152
- height: sq,
153
- backgroundColor: color,
154
- borderRadius: size * 0.05,
155
- }} />
156
- </View>
157
- );
158
- }
159
-
160
- // ─── Recording Dot (pulsing filled circle) ────────────────────
161
-
162
- export function RecordingDot({ size = 18, color = '#FF3B30' }: { size?: number; color?: string }) {
163
- const dotSize = size * 0.45;
164
- return (
165
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
166
- <View style={{
167
- width: dotSize,
168
- height: dotSize,
169
- borderRadius: dotSize / 2,
170
- backgroundColor: color,
171
- }} />
172
- </View>
173
- );
174
- }
175
-
176
- // ─── Loading Spinner (three dots) ─────────────────────────────
177
-
178
- export function LoadingDots({ size = 18, color = '#fff' }: { size?: number; color?: string }) {
179
- const dotSize = size * 0.15;
180
- return (
181
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center', flexDirection: 'row', gap: dotSize * 0.8 }}>
182
- {[0.4, 0.7, 1].map((opacity, i) => (
183
- <View key={i} style={{
184
- width: dotSize,
185
- height: dotSize,
186
- borderRadius: dotSize / 2,
187
- backgroundColor: color,
188
- opacity,
189
- }} />
190
- ))}
191
- </View>
192
- );
193
- }
194
-
195
- // ─── Close / Dismiss (X mark) ─────────────────────────────────
196
-
197
- export function CloseIcon({ size = 14, color = 'rgba(255,255,255,0.6)' }: { size?: number; color?: string }) {
198
- const barW = size * 0.7;
199
- const barH = size * 0.12;
200
- return (
201
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
202
- <View style={{
203
- position: 'absolute',
204
- width: barW,
205
- height: barH,
206
- backgroundColor: color,
207
- borderRadius: barH,
208
- transform: [{ rotate: '45deg' }],
209
- }} />
210
- <View style={{
211
- position: 'absolute',
212
- width: barW,
213
- height: barH,
214
- backgroundColor: color,
215
- borderRadius: barH,
216
- transform: [{ rotate: '-45deg' }],
217
- }} />
218
- </View>
219
- );
220
- }
221
-
222
- // ─── AI Badge (for FAB) ───────────────────────────────────────
223
-
224
- export function AIBadge({ size = 28 }: { size?: number }) {
225
- // Chat bubble — clean, universally represents AI assistant
226
- const bubbleW = size * 0.6;
227
- const bubbleH = size * 0.45;
228
- const tailSize = size * 0.12;
229
- return (
230
- <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
231
- {/* Bubble body */}
232
- <View style={{
233
- width: bubbleW,
234
- height: bubbleH,
235
- backgroundColor: '#fff',
236
- borderRadius: size * 0.12,
237
- marginBottom: tailSize * 0.5,
238
- }} />
239
- {/* Tail (small triangle at bottom-left) */}
240
- <View style={{
241
- position: 'absolute',
242
- bottom: size * 0.18,
243
- left: size * 0.22,
244
- width: 0,
245
- height: 0,
246
- borderTopWidth: tailSize,
247
- borderTopColor: '#fff',
248
- borderRightWidth: tailSize,
249
- borderRightColor: 'transparent',
250
- }} />
251
- </View>
252
- );
253
- }