@qafka/react-native 2.0.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.
Files changed (178) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/CONTRIBUTING.md +92 -0
  3. package/LICENSE +22 -0
  4. package/README.md +109 -0
  5. package/SECURITY.md +67 -0
  6. package/android/build.gradle +35 -0
  7. package/android/src/main/AndroidManifest.xml +2 -0
  8. package/android/src/main/java/com/qafka/attestation/QafkaAttestationModule.kt +92 -0
  9. package/android/src/main/java/com/qafka/attestation/QafkaAttestationPackage.kt +22 -0
  10. package/android/src/main/java/com/qafka/audio/QafkaAudioModule.kt +290 -0
  11. package/android/src/main/java/com/qafka/clipboard/QafkaClipboardModule.kt +28 -0
  12. package/android/src/main/java/com/qafka/storage/QafkaStorageModule.kt +80 -0
  13. package/app.plugin.js +1 -0
  14. package/dist/QafkaSDK.d.ts +174 -0
  15. package/dist/QafkaSDK.js +461 -0
  16. package/dist/cards/bindings/resolveFieldName.d.ts +25 -0
  17. package/dist/cards/bindings/resolveFieldName.js +82 -0
  18. package/dist/cards/cta/CardContext.d.ts +16 -0
  19. package/dist/cards/cta/CardContext.js +58 -0
  20. package/dist/cards/cta/dispatcher.d.ts +7 -0
  21. package/dist/cards/cta/dispatcher.js +90 -0
  22. package/dist/cards/cta/types.d.ts +66 -0
  23. package/dist/cards/cta/types.js +2 -0
  24. package/dist/cards/index.d.ts +20 -0
  25. package/dist/cards/index.js +34 -0
  26. package/dist/cards/primitives/QButton.d.ts +10 -0
  27. package/dist/cards/primitives/QButton.js +115 -0
  28. package/dist/cards/primitives/QDivider.d.ts +7 -0
  29. package/dist/cards/primitives/QDivider.js +17 -0
  30. package/dist/cards/primitives/QIcon.d.ts +13 -0
  31. package/dist/cards/primitives/QIcon.js +26 -0
  32. package/dist/cards/primitives/QImage.d.ts +9 -0
  33. package/dist/cards/primitives/QImage.js +22 -0
  34. package/dist/cards/primitives/QText.d.ts +9 -0
  35. package/dist/cards/primitives/QText.js +30 -0
  36. package/dist/cards/primitives/QView.d.ts +8 -0
  37. package/dist/cards/primitives/QView.js +19 -0
  38. package/dist/cards/renderer/CardRenderer.d.ts +19 -0
  39. package/dist/cards/renderer/CardRenderer.js +64 -0
  40. package/dist/cards/renderer/renderNode.d.ts +13 -0
  41. package/dist/cards/renderer/renderNode.js +42 -0
  42. package/dist/cards/types.d.ts +110 -0
  43. package/dist/cards/types.js +6 -0
  44. package/dist/components/ActionResultBadge.d.ts +12 -0
  45. package/dist/components/ActionResultBadge.js +58 -0
  46. package/dist/components/ChatPage.d.ts +44 -0
  47. package/dist/components/ChatPage.js +84 -0
  48. package/dist/components/DataChip.d.ts +8 -0
  49. package/dist/components/DataChip.js +80 -0
  50. package/dist/components/DataChipList.d.ts +13 -0
  51. package/dist/components/DataChipList.js +21 -0
  52. package/dist/components/FloatingButton.d.ts +11 -0
  53. package/dist/components/FloatingButton.js +162 -0
  54. package/dist/components/InputArea.d.ts +57 -0
  55. package/dist/components/InputArea.js +142 -0
  56. package/dist/components/MarkdownText.d.ts +15 -0
  57. package/dist/components/MarkdownText.js +283 -0
  58. package/dist/components/MessageBubble.d.ts +134 -0
  59. package/dist/components/MessageBubble.js +384 -0
  60. package/dist/components/NavigationSuggestion.d.ts +11 -0
  61. package/dist/components/NavigationSuggestion.js +109 -0
  62. package/dist/components/Qafka.d.ts +39 -0
  63. package/dist/components/Qafka.handlers.d.ts +21 -0
  64. package/dist/components/Qafka.handlers.js +54 -0
  65. package/dist/components/Qafka.js +493 -0
  66. package/dist/components/Qafka.styles.d.ts +19 -0
  67. package/dist/components/Qafka.styles.js +101 -0
  68. package/dist/components/Qafka.types.d.ts +744 -0
  69. package/dist/components/Qafka.types.js +2 -0
  70. package/dist/components/Qafka.utils.d.ts +7 -0
  71. package/dist/components/Qafka.utils.js +34 -0
  72. package/dist/components/QafkaProvider.d.ts +12 -0
  73. package/dist/components/QafkaProvider.js +87 -0
  74. package/dist/components/QuickReplies.d.ts +14 -0
  75. package/dist/components/QuickReplies.js +48 -0
  76. package/dist/components/StepProgressIndicator.d.ts +12 -0
  77. package/dist/components/StepProgressIndicator.js +48 -0
  78. package/dist/components/SuggestionButton.d.ts +42 -0
  79. package/dist/components/SuggestionButton.js +67 -0
  80. package/dist/components/ToolStatusPill.d.ts +20 -0
  81. package/dist/components/ToolStatusPill.js +43 -0
  82. package/dist/components/TypingIndicator.d.ts +28 -0
  83. package/dist/components/TypingIndicator.js +109 -0
  84. package/dist/components/VoicePage.d.ts +48 -0
  85. package/dist/components/VoicePage.js +683 -0
  86. package/dist/components/defaults/DefaultCard.d.ts +14 -0
  87. package/dist/components/defaults/DefaultCard.js +156 -0
  88. package/dist/components/defaults/DefaultDetail.d.ts +14 -0
  89. package/dist/components/defaults/DefaultDetail.js +138 -0
  90. package/dist/components/defaults/DefaultList.d.ts +12 -0
  91. package/dist/components/defaults/DefaultList.js +98 -0
  92. package/dist/components/defaults/DefaultTable.d.ts +14 -0
  93. package/dist/components/defaults/DefaultTable.js +204 -0
  94. package/dist/components/defaults/index.d.ts +14 -0
  95. package/dist/components/defaults/index.js +25 -0
  96. package/dist/components/index.d.ts +22 -0
  97. package/dist/components/index.js +36 -0
  98. package/dist/constants.d.ts +10 -0
  99. package/dist/constants.js +13 -0
  100. package/dist/hooks/useChatMessages.d.ts +72 -0
  101. package/dist/hooks/useChatMessages.js +505 -0
  102. package/dist/hooks/useContextManager.d.ts +12 -0
  103. package/dist/hooks/useContextManager.js +46 -0
  104. package/dist/hooks/useProjectTheme.d.ts +19 -0
  105. package/dist/hooks/useProjectTheme.js +163 -0
  106. package/dist/hooks/useSDK.d.ts +31 -0
  107. package/dist/hooks/useSDK.js +103 -0
  108. package/dist/hooks/useVoiceChat.d.ts +110 -0
  109. package/dist/hooks/useVoiceChat.js +436 -0
  110. package/dist/index.d.ts +13 -0
  111. package/dist/index.js +59 -0
  112. package/dist/native/QafkaAttestation.d.ts +23 -0
  113. package/dist/native/QafkaAttestation.js +70 -0
  114. package/dist/native/QafkaAudio.d.ts +14 -0
  115. package/dist/native/QafkaAudio.js +31 -0
  116. package/dist/native/QafkaClipboard.d.ts +11 -0
  117. package/dist/native/QafkaClipboard.js +14 -0
  118. package/dist/native/QafkaStorage.d.ts +15 -0
  119. package/dist/native/QafkaStorage.js +12 -0
  120. package/dist/resolve-project-config.d.ts +35 -0
  121. package/dist/resolve-project-config.js +41 -0
  122. package/dist/runtime-config-loader.d.ts +37 -0
  123. package/dist/runtime-config-loader.js +53 -0
  124. package/dist/services/AttestationManager.d.ts +38 -0
  125. package/dist/services/AttestationManager.js +296 -0
  126. package/dist/services/BackendService.d.ts +156 -0
  127. package/dist/services/BackendService.js +755 -0
  128. package/dist/services/ConversationManager.d.ts +43 -0
  129. package/dist/services/ConversationManager.js +96 -0
  130. package/dist/services/NavigationHandler.d.ts +29 -0
  131. package/dist/services/NavigationHandler.js +70 -0
  132. package/dist/services/RealtimeService.d.ts +83 -0
  133. package/dist/services/RealtimeService.js +203 -0
  134. package/dist/services/storage.d.ts +11 -0
  135. package/dist/services/storage.js +15 -0
  136. package/dist/services/storageCore.d.ts +17 -0
  137. package/dist/services/storageCore.js +46 -0
  138. package/dist/themes/dark.d.ts +5 -0
  139. package/dist/themes/dark.js +129 -0
  140. package/dist/themes/index.d.ts +12 -0
  141. package/dist/themes/index.js +33 -0
  142. package/dist/themes/light.d.ts +5 -0
  143. package/dist/themes/light.js +129 -0
  144. package/dist/themes/types.d.ts +155 -0
  145. package/dist/themes/types.js +5 -0
  146. package/dist/types/chat.d.ts +126 -0
  147. package/dist/types/chat.js +5 -0
  148. package/dist/types/components.d.ts +56 -0
  149. package/dist/types/components.js +16 -0
  150. package/dist/types/external-navigation.d.ts +19 -0
  151. package/dist/types/external-navigation.js +8 -0
  152. package/dist/types/index.d.ts +9 -0
  153. package/dist/types/index.js +25 -0
  154. package/dist/types/navigation.d.ts +86 -0
  155. package/dist/types/navigation.js +5 -0
  156. package/dist/types/sdk.d.ts +36 -0
  157. package/dist/types/sdk.js +5 -0
  158. package/dist/utils/deepMerge.d.ts +46 -0
  159. package/dist/utils/deepMerge.js +70 -0
  160. package/dist/utils/fontUtils.d.ts +8 -0
  161. package/dist/utils/fontUtils.js +16 -0
  162. package/dist/validate-end-user.d.ts +18 -0
  163. package/dist/validate-end-user.js +74 -0
  164. package/expo-plugin/withQafkaAttestation.js +57 -0
  165. package/ios/QafkaAttestation.m +25 -0
  166. package/ios/QafkaAttestation.swift +128 -0
  167. package/ios/QafkaAudio.m +23 -0
  168. package/ios/QafkaAudio.swift +519 -0
  169. package/ios/QafkaClipboard.m +10 -0
  170. package/ios/QafkaClipboard.swift +21 -0
  171. package/ios/QafkaReactImports.h +2 -0
  172. package/ios/QafkaStorage.m +26 -0
  173. package/ios/QafkaStorage.swift +118 -0
  174. package/package.json +82 -0
  175. package/qafka.config.d.ts +9 -0
  176. package/qafka.config.js +9 -0
  177. package/react-native-qafka.podspec +28 -0
  178. package/react-native.config.js +14 -0
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Build action buttons from chat response (navigation only).
3
+ *
4
+ * @param response - The chat response with optional `navigationSuggestion`.
5
+ * @param navigationLabelFormat - Optional formatter for the button label given a screen name.
6
+ */
7
+ export declare const buildActionButtons: (response: any, navigationLabelFormat?: (screenName: string) => string) => any[];
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildActionButtons = void 0;
4
+ /**
5
+ * Build action buttons from chat response (navigation only).
6
+ *
7
+ * @param response - The chat response with optional `navigationSuggestion`.
8
+ * @param navigationLabelFormat - Optional formatter for the button label given a screen name.
9
+ */
10
+ const buildActionButtons = (response, navigationLabelFormat) => {
11
+ const actionButtons = [];
12
+ if (response.navigationSuggestion) {
13
+ const screenName = response.navigationSuggestion.screenName;
14
+ let label;
15
+ if (navigationLabelFormat && screenName) {
16
+ label = navigationLabelFormat(screenName);
17
+ }
18
+ else if (response.navigationSuggestion.message) {
19
+ label = response.navigationSuggestion.message;
20
+ }
21
+ else {
22
+ label = `Navigate to ${screenName || 'screen'}`;
23
+ }
24
+ actionButtons.push({
25
+ id: `nav-${Date.now()}`,
26
+ type: 'navigation',
27
+ label,
28
+ data: response.navigationSuggestion,
29
+ style: 'primary',
30
+ });
31
+ }
32
+ return actionButtons;
33
+ };
34
+ exports.buildActionButtons = buildActionButtons;
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { QafkaProps } from './Qafka.types';
3
+ type QafkaProviderProps = Pick<QafkaProps, 'style' | 'apiUrl' | 'theme' | 'themeOverride' | 'customTheme' | 'enableStreaming' | 'isAuthenticated' | 'endUserId' | 'endUserData' | 'context' | 'contextDescription' | 'components' | 'showTimestamps' | 'placeholder' | 'maxMessageLength' | 'greetingMessage' | 'title' | 'showHeader' | 'onReady' | 'onMessageSent' | 'onResponseReceived' | 'onError' | 'onNavigationSuggest' | 'onNavigationAction' | 'onToolSuggested' | 'onActionResult' | 'onStepCompleted' | 'onClose' | 'onBack' | 'CloseComponent' | 'BackComponent' | 'navigationLabelFormat' | 'NavigationButtonComponent'> & {
4
+ mode?: 'floating' | 'fullscreen' | 'inline';
5
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
6
+ };
7
+ /**
8
+ * QafkaProvider - Main component that connects UI with SDK
9
+ * This is what users will import and use in their app
10
+ */
11
+ export declare function QafkaProvider({ mode, position, theme: themeProp, ...qafkaProps }: QafkaProviderProps): React.JSX.Element;
12
+ export {};
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.QafkaProvider = QafkaProvider;
37
+ const react_1 = __importStar(require("react"));
38
+ const Qafka_1 = require("./Qafka");
39
+ const FloatingButton_1 = require("./FloatingButton");
40
+ const themes_1 = require("../themes");
41
+ const react_native_1 = require("react-native");
42
+ /**
43
+ * QafkaProvider - Main component that connects UI with SDK
44
+ * This is what users will import and use in their app
45
+ */
46
+ function QafkaProvider({ mode = 'floating', position = 'bottom-right', theme: themeProp = 'light', ...qafkaProps }) {
47
+ const [isOpen, setIsOpen] = (0, react_1.useState)(mode !== 'floating');
48
+ // Get theme
49
+ const theme = typeof themeProp === 'string'
50
+ ? themeProp === 'dark'
51
+ ? themes_1.darkTheme
52
+ : themes_1.lightTheme
53
+ : themeProp;
54
+ const handleToggle = () => {
55
+ setIsOpen((prev) => !prev);
56
+ };
57
+ // Floating mode with button
58
+ if (mode === 'floating') {
59
+ return (<react_native_1.View style={styles.container} pointerEvents="box-none">
60
+ {isOpen && (<react_native_1.View style={styles.widgetContainer}>
61
+ <Qafka_1.Qafka {...qafkaProps} theme={theme}/>
62
+ </react_native_1.View>)}
63
+ <FloatingButton_1.FloatingButton isOpen={isOpen} onPress={handleToggle} theme={theme} position={position}/>
64
+ </react_native_1.View>);
65
+ }
66
+ // Fullscreen or inline mode
67
+ return (<Qafka_1.Qafka {...qafkaProps} theme={theme} mode={mode}/>);
68
+ }
69
+ const styles = react_native_1.StyleSheet.create({
70
+ container: {
71
+ ...react_native_1.StyleSheet.absoluteFill,
72
+ zIndex: 9999,
73
+ },
74
+ widgetContainer: {
75
+ position: 'absolute',
76
+ bottom: 100,
77
+ right: 24,
78
+ width: 360,
79
+ height: 600,
80
+ maxHeight: '80%',
81
+ shadowColor: '#000',
82
+ shadowOffset: { width: 0, height: 4 },
83
+ shadowOpacity: 0.3,
84
+ shadowRadius: 8,
85
+ elevation: 8,
86
+ },
87
+ });
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import type { Theme } from '../themes';
3
+ interface QuickReply {
4
+ id: string;
5
+ text: string;
6
+ payload?: string;
7
+ }
8
+ interface QuickRepliesProps {
9
+ replies: QuickReply[];
10
+ onSelect: (reply: QuickReply) => void;
11
+ theme: Theme;
12
+ }
13
+ export declare function QuickReplies({ replies, onSelect, theme }: QuickRepliesProps): React.JSX.Element | null;
14
+ export {};
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QuickReplies = QuickReplies;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ function QuickReplies({ replies, onSelect, theme }) {
10
+ if (!replies || replies.length === 0) {
11
+ return null;
12
+ }
13
+ return (<react_native_1.View style={[styles.container, { backgroundColor: theme.colors.background }]}>
14
+ <react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={styles.scrollContent}>
15
+ {replies.map((reply) => (<react_native_1.TouchableOpacity key={reply.id} style={[
16
+ styles.button,
17
+ {
18
+ backgroundColor: theme.colors.surface,
19
+ borderColor: theme.colors.primary,
20
+ },
21
+ ]} onPress={() => onSelect(reply)} activeOpacity={0.7}>
22
+ <react_native_1.Text style={[styles.text, { color: theme.colors.primary }]} numberOfLines={1}>
23
+ {reply.text}
24
+ </react_native_1.Text>
25
+ </react_native_1.TouchableOpacity>))}
26
+ </react_native_1.ScrollView>
27
+ </react_native_1.View>);
28
+ }
29
+ const styles = react_native_1.StyleSheet.create({
30
+ container: {
31
+ paddingVertical: 8,
32
+ },
33
+ scrollContent: {
34
+ paddingHorizontal: 16,
35
+ gap: 8,
36
+ },
37
+ button: {
38
+ paddingHorizontal: 16,
39
+ paddingVertical: 10,
40
+ borderRadius: 20,
41
+ borderWidth: 1,
42
+ maxWidth: 200,
43
+ },
44
+ text: {
45
+ fontSize: 14,
46
+ fontWeight: '500',
47
+ },
48
+ });
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { Theme } from '../themes/types';
3
+ interface StepProgressIndicatorProps {
4
+ steps: Array<{
5
+ tool: string;
6
+ step: string;
7
+ data: Record<string, any>;
8
+ }>;
9
+ theme: Theme;
10
+ }
11
+ export declare function StepProgressIndicator({ steps, theme }: StepProgressIndicatorProps): React.JSX.Element | null;
12
+ export {};
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.StepProgressIndicator = StepProgressIndicator;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ function StepProgressIndicator({ steps, theme }) {
10
+ if (!steps || steps.length === 0)
11
+ return null;
12
+ return (<react_native_1.View style={styles.container}>
13
+ {steps.map((step, index) => (<react_native_1.View key={index} style={styles.stepRow}>
14
+ <react_native_1.View style={[
15
+ styles.dot,
16
+ { backgroundColor: theme.colors.success || '#22c55e' },
17
+ ]}/>
18
+ <react_native_1.Text style={[
19
+ styles.stepText,
20
+ {
21
+ color: theme.colors.textSecondary,
22
+ fontSize: theme.typography.fontSize.xs,
23
+ },
24
+ ]} numberOfLines={1}>
25
+ {step.step}
26
+ </react_native_1.Text>
27
+ </react_native_1.View>))}
28
+ </react_native_1.View>);
29
+ }
30
+ const styles = react_native_1.StyleSheet.create({
31
+ container: {
32
+ marginTop: 6,
33
+ gap: 3,
34
+ },
35
+ stepRow: {
36
+ flexDirection: 'row',
37
+ alignItems: 'center',
38
+ gap: 6,
39
+ },
40
+ dot: {
41
+ width: 6,
42
+ height: 6,
43
+ borderRadius: 3,
44
+ },
45
+ stepText: {
46
+ fontWeight: '400',
47
+ },
48
+ });
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { Theme } from '../themes/types';
3
+ import { NavigationSuggestion } from '../types/navigation';
4
+ import { ExternalSuggestion } from '../types/external-navigation';
5
+ /**
6
+ * Discriminated union representing any suggestion the SDK can render
7
+ * as a single tappable button under an assistant message.
8
+ *
9
+ * - `navigation` — internal route suggestion (Expo Router / React Nav)
10
+ * - `external` — outbound link (WhatsApp, phone, map, app store, …)
11
+ * - `tool` — generic tool-triggered action button
12
+ */
13
+ export type AnySuggestion = {
14
+ kind: 'navigation';
15
+ data: NavigationSuggestion;
16
+ label?: string;
17
+ } | {
18
+ kind: 'external';
19
+ data: ExternalSuggestion;
20
+ } | {
21
+ kind: 'tool';
22
+ data: {
23
+ id?: string;
24
+ toolId?: string;
25
+ label?: string;
26
+ icon?: string;
27
+ };
28
+ };
29
+ export interface SuggestionButtonProps {
30
+ suggestion: AnySuggestion;
31
+ onPress: () => void;
32
+ theme?: Theme;
33
+ }
34
+ /**
35
+ * Generic suggestion button used for navigation / external / tool suggestions.
36
+ *
37
+ * Host apps may override rendering by supplying their own component through
38
+ * the `QafkaProps.NavigationButtonComponent` prop (for navigation suggestions)
39
+ * or by providing a custom `onExternalSuggestion` callback that renders its
40
+ * own UI before calling the handler.
41
+ */
42
+ export declare function SuggestionButton({ suggestion, onPress, theme, }: SuggestionButtonProps): React.JSX.Element;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SuggestionButton = SuggestionButton;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const fontUtils_1 = require("../utils/fontUtils");
10
+ /**
11
+ * Generic suggestion button used for navigation / external / tool suggestions.
12
+ *
13
+ * Host apps may override rendering by supplying their own component through
14
+ * the `QafkaProps.NavigationButtonComponent` prop (for navigation suggestions)
15
+ * or by providing a custom `onExternalSuggestion` callback that renders its
16
+ * own UI before calling the handler.
17
+ */
18
+ function SuggestionButton({ suggestion, onPress, theme, }) {
19
+ const { label, icon } = resolveDisplay(suggestion);
20
+ // Pick colors from theme when available, fall back to SDK defaults so this
21
+ // component is usable standalone (e.g. in tests or previews).
22
+ const bg = theme?.colors?.primary ?? '#0066CC';
23
+ const fg = '#ffffff';
24
+ const buttonStyle = {
25
+ flexDirection: 'row',
26
+ alignItems: 'center',
27
+ justifyContent: 'center',
28
+ backgroundColor: bg,
29
+ paddingHorizontal: theme?.spacing?.md ?? 16,
30
+ paddingVertical: theme?.spacing?.sm ?? 8,
31
+ borderRadius: theme?.borderRadius?.md ?? 8,
32
+ marginTop: theme?.spacing?.xs ?? 4,
33
+ ...(theme?.shadows?.small ?? {}),
34
+ };
35
+ const labelStyle = {
36
+ color: fg,
37
+ fontSize: theme?.typography?.fontSize?.sm ?? 14,
38
+ fontWeight: theme?.typography?.fontWeight?.medium ?? '500',
39
+ marginLeft: icon ? (theme?.spacing?.xs ?? 4) : 0,
40
+ fontFamily: theme ? (0, fontUtils_1.getFontFamily)(theme, 'medium') : undefined,
41
+ };
42
+ return (<react_native_1.TouchableOpacity onPress={onPress} style={buttonStyle} activeOpacity={0.7} accessibilityRole="button" accessibilityLabel={label}>
43
+ {icon ? (<react_native_1.Text style={[styles.icon, { color: fg }]}>{formatIcon(icon)}</react_native_1.Text>) : null}
44
+ <react_native_1.Text style={labelStyle}>{label}</react_native_1.Text>
45
+ </react_native_1.TouchableOpacity>);
46
+ }
47
+ function resolveDisplay(s) {
48
+ if (s.kind === 'navigation') {
49
+ return { label: s.label ?? s.data.screenName };
50
+ }
51
+ if (s.kind === 'external') {
52
+ return { label: s.data.label, icon: s.data.icon };
53
+ }
54
+ return { label: s.data.label ?? 'Action', icon: s.data.icon };
55
+ }
56
+ /**
57
+ * SDK icons come through as string names (e.g. `logo-whatsapp`, `phone`) to
58
+ * stay renderer-agnostic. Without a concrete icon library we cannot draw the
59
+ * glyph here, so we return an empty string. Host apps that want rich icons
60
+ * can wrap/replace this component and use e.g. `react-native-vector-icons`.
61
+ */
62
+ function formatIcon(_iconName) {
63
+ return '';
64
+ }
65
+ const styles = react_native_1.StyleSheet.create({
66
+ icon: { marginRight: 8, fontSize: 16 },
67
+ });
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ export interface ToolStatusPillProps {
3
+ message: string;
4
+ theme?: {
5
+ colors?: {
6
+ aiBubble?: string;
7
+ textSecondary?: string;
8
+ primary?: string;
9
+ };
10
+ borderRadius?: {
11
+ lg?: number;
12
+ };
13
+ };
14
+ }
15
+ /**
16
+ * ToolStatusPill — shown while a server-side tool fetch or an AI follow-up
17
+ * round-trip is running (server-managed execution modes).
18
+ * Displays the loadingMessage next to a spinner.
19
+ */
20
+ export declare const ToolStatusPill: React.FC<ToolStatusPillProps>;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ToolStatusPill = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ /**
10
+ * ToolStatusPill — shown while a server-side tool fetch or an AI follow-up
11
+ * round-trip is running (server-managed execution modes).
12
+ * Displays the loadingMessage next to a spinner.
13
+ */
14
+ const ToolStatusPill = ({ message, theme, }) => {
15
+ const pillStyle = {
16
+ backgroundColor: theme?.colors?.aiBubble || '#f3f4f6',
17
+ borderRadius: theme?.borderRadius?.lg || 16,
18
+ };
19
+ const textStyle = {
20
+ color: theme?.colors?.textSecondary || '#6b7280',
21
+ };
22
+ const spinnerColor = theme?.colors?.primary || '#6b7280';
23
+ return (<react_native_1.View style={[styles.pill, pillStyle]}>
24
+ <react_native_1.ActivityIndicator size="small" color={spinnerColor}/>
25
+ <react_native_1.Text style={[styles.text, textStyle]}>{message}</react_native_1.Text>
26
+ </react_native_1.View>);
27
+ };
28
+ exports.ToolStatusPill = ToolStatusPill;
29
+ const styles = react_native_1.StyleSheet.create({
30
+ pill: {
31
+ flexDirection: 'row',
32
+ alignItems: 'center',
33
+ paddingHorizontal: 12,
34
+ paddingVertical: 8,
35
+ alignSelf: 'flex-start',
36
+ marginVertical: 4,
37
+ marginLeft: 8,
38
+ },
39
+ text: {
40
+ marginLeft: 8,
41
+ fontSize: 13,
42
+ },
43
+ });
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { Theme } from '../themes/types';
3
+ export interface TypingIndicatorProps {
4
+ /**
5
+ * Theme configuration
6
+ */
7
+ theme: Theme;
8
+ /**
9
+ * Size of the dots
10
+ */
11
+ dotSize?: number;
12
+ /**
13
+ * Color of the dots (overrides theme)
14
+ */
15
+ dotColor?: string;
16
+ }
17
+ /**
18
+ * TypingIndicator Component
19
+ *
20
+ * Animated three-dot indicator showing AI is typing.
21
+ * Each dot bounces with a slight delay creating a wave effect.
22
+ *
23
+ * @example
24
+ * ```tsx
25
+ * {isTyping && <TypingIndicator theme={lightTheme} />}
26
+ * ```
27
+ */
28
+ export declare function TypingIndicator({ theme, dotSize, dotColor, }: TypingIndicatorProps): React.JSX.Element;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TypingIndicator = TypingIndicator;
37
+ const react_1 = __importStar(require("react"));
38
+ const react_native_1 = require("react-native");
39
+ /**
40
+ * TypingIndicator Component
41
+ *
42
+ * Animated three-dot indicator showing AI is typing.
43
+ * Each dot bounces with a slight delay creating a wave effect.
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * {isTyping && <TypingIndicator theme={lightTheme} />}
48
+ * ```
49
+ */
50
+ function TypingIndicator({ theme, dotSize = 8, dotColor, }) {
51
+ // Animation values for each dot
52
+ const dot1Anim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
53
+ const dot2Anim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
54
+ const dot3Anim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
55
+ (0, react_1.useEffect)(() => {
56
+ // Create bounce animation for a single dot
57
+ const createBounceAnimation = (animValue, delay) => {
58
+ return react_native_1.Animated.sequence([
59
+ react_native_1.Animated.delay(delay),
60
+ react_native_1.Animated.loop(react_native_1.Animated.sequence([
61
+ react_native_1.Animated.timing(animValue, {
62
+ toValue: -8,
63
+ duration: theme.animation.duration.normal,
64
+ useNativeDriver: true,
65
+ }),
66
+ react_native_1.Animated.timing(animValue, {
67
+ toValue: 0,
68
+ duration: theme.animation.duration.normal,
69
+ useNativeDriver: true,
70
+ }),
71
+ ])),
72
+ ]);
73
+ };
74
+ // Start animations with staggered delays
75
+ const animation = react_native_1.Animated.parallel([
76
+ createBounceAnimation(dot1Anim, 0),
77
+ createBounceAnimation(dot2Anim, 150),
78
+ createBounceAnimation(dot3Anim, 300),
79
+ ]);
80
+ animation.start();
81
+ return () => {
82
+ animation.stop();
83
+ };
84
+ }, [dot1Anim, dot2Anim, dot3Anim, theme.animation.duration.normal]);
85
+ const containerStyle = {
86
+ flexDirection: 'row',
87
+ alignItems: 'center',
88
+ alignSelf: 'flex-start',
89
+ backgroundColor: theme.colors.aiBubble,
90
+ borderRadius: theme.borderRadius.lg,
91
+ paddingHorizontal: theme.spacing.md,
92
+ paddingVertical: theme.spacing.sm + 2,
93
+ marginBottom: theme.spacing.sm,
94
+ ...theme.shadows.small,
95
+ };
96
+ const dotStyle = (animValue) => ({
97
+ width: dotSize,
98
+ height: dotSize,
99
+ borderRadius: dotSize / 2,
100
+ backgroundColor: dotColor || theme.colors.textSecondary,
101
+ marginHorizontal: theme.spacing.xs / 2,
102
+ transform: [{ translateY: animValue }],
103
+ });
104
+ return (<react_native_1.View style={containerStyle}>
105
+ <react_native_1.Animated.View style={dotStyle(dot1Anim)}/>
106
+ <react_native_1.Animated.View style={dotStyle(dot2Anim)}/>
107
+ <react_native_1.Animated.View style={dotStyle(dot3Anim)}/>
108
+ </react_native_1.View>);
109
+ }
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import type { ComponentType } from 'react';
3
+ import type { VoiceComponents, VoiceTranscriptMode, VoiceTranscriptTurn } from './Qafka.types';
4
+ export type VoiceChatState = 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking';
5
+ interface VoiceToolStatusShape {
6
+ toolCallId: string;
7
+ toolKey: string;
8
+ loadingMessage: string;
9
+ }
10
+ type VoiceRenderedToolShape = {
11
+ kind?: 'tool';
12
+ toolCallId: string;
13
+ toolKey: string;
14
+ data: any;
15
+ tool: any;
16
+ } | {
17
+ kind: 'display';
18
+ toolCallId: string;
19
+ items: Array<{
20
+ label: string;
21
+ value: string;
22
+ copyable?: boolean;
23
+ }>;
24
+ };
25
+ interface VoicePageProps {
26
+ state: VoiceChatState;
27
+ transcript: string;
28
+ userTranscript: string;
29
+ transcriptHistory?: VoiceTranscriptTurn[];
30
+ transcriptMode?: VoiceTranscriptMode;
31
+ amplitude: number;
32
+ theme: any;
33
+ voiceComponents?: VoiceComponents;
34
+ toolStatus?: VoiceToolStatusShape | null;
35
+ renderedTools?: VoiceRenderedToolShape[];
36
+ registeredComponents?: Record<string, ComponentType<{
37
+ data: any;
38
+ }>>;
39
+ transcriptOverrideForTurn?: boolean;
40
+ DataChipListComponent?: ComponentType<{
41
+ items: any[];
42
+ theme?: any;
43
+ }>;
44
+ isMuted?: boolean;
45
+ onToggleMute?: () => void;
46
+ }
47
+ export declare function VoicePage({ state, transcript, userTranscript, transcriptHistory, transcriptMode, amplitude, theme, voiceComponents, toolStatus, renderedTools, registeredComponents, transcriptOverrideForTurn, DataChipListComponent, isMuted, onToggleMute, }: VoicePageProps): React.JSX.Element;
48
+ export {};