@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.
- package/CHANGELOG.md +12 -0
- package/CONTRIBUTING.md +92 -0
- package/LICENSE +22 -0
- package/README.md +109 -0
- package/SECURITY.md +67 -0
- package/android/build.gradle +35 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/qafka/attestation/QafkaAttestationModule.kt +92 -0
- package/android/src/main/java/com/qafka/attestation/QafkaAttestationPackage.kt +22 -0
- package/android/src/main/java/com/qafka/audio/QafkaAudioModule.kt +290 -0
- package/android/src/main/java/com/qafka/clipboard/QafkaClipboardModule.kt +28 -0
- package/android/src/main/java/com/qafka/storage/QafkaStorageModule.kt +80 -0
- package/app.plugin.js +1 -0
- package/dist/QafkaSDK.d.ts +174 -0
- package/dist/QafkaSDK.js +461 -0
- package/dist/cards/bindings/resolveFieldName.d.ts +25 -0
- package/dist/cards/bindings/resolveFieldName.js +82 -0
- package/dist/cards/cta/CardContext.d.ts +16 -0
- package/dist/cards/cta/CardContext.js +58 -0
- package/dist/cards/cta/dispatcher.d.ts +7 -0
- package/dist/cards/cta/dispatcher.js +90 -0
- package/dist/cards/cta/types.d.ts +66 -0
- package/dist/cards/cta/types.js +2 -0
- package/dist/cards/index.d.ts +20 -0
- package/dist/cards/index.js +34 -0
- package/dist/cards/primitives/QButton.d.ts +10 -0
- package/dist/cards/primitives/QButton.js +115 -0
- package/dist/cards/primitives/QDivider.d.ts +7 -0
- package/dist/cards/primitives/QDivider.js +17 -0
- package/dist/cards/primitives/QIcon.d.ts +13 -0
- package/dist/cards/primitives/QIcon.js +26 -0
- package/dist/cards/primitives/QImage.d.ts +9 -0
- package/dist/cards/primitives/QImage.js +22 -0
- package/dist/cards/primitives/QText.d.ts +9 -0
- package/dist/cards/primitives/QText.js +30 -0
- package/dist/cards/primitives/QView.d.ts +8 -0
- package/dist/cards/primitives/QView.js +19 -0
- package/dist/cards/renderer/CardRenderer.d.ts +19 -0
- package/dist/cards/renderer/CardRenderer.js +64 -0
- package/dist/cards/renderer/renderNode.d.ts +13 -0
- package/dist/cards/renderer/renderNode.js +42 -0
- package/dist/cards/types.d.ts +110 -0
- package/dist/cards/types.js +6 -0
- package/dist/components/ActionResultBadge.d.ts +12 -0
- package/dist/components/ActionResultBadge.js +58 -0
- package/dist/components/ChatPage.d.ts +44 -0
- package/dist/components/ChatPage.js +84 -0
- package/dist/components/DataChip.d.ts +8 -0
- package/dist/components/DataChip.js +80 -0
- package/dist/components/DataChipList.d.ts +13 -0
- package/dist/components/DataChipList.js +21 -0
- package/dist/components/FloatingButton.d.ts +11 -0
- package/dist/components/FloatingButton.js +162 -0
- package/dist/components/InputArea.d.ts +57 -0
- package/dist/components/InputArea.js +142 -0
- package/dist/components/MarkdownText.d.ts +15 -0
- package/dist/components/MarkdownText.js +283 -0
- package/dist/components/MessageBubble.d.ts +134 -0
- package/dist/components/MessageBubble.js +384 -0
- package/dist/components/NavigationSuggestion.d.ts +11 -0
- package/dist/components/NavigationSuggestion.js +109 -0
- package/dist/components/Qafka.d.ts +39 -0
- package/dist/components/Qafka.handlers.d.ts +21 -0
- package/dist/components/Qafka.handlers.js +54 -0
- package/dist/components/Qafka.js +493 -0
- package/dist/components/Qafka.styles.d.ts +19 -0
- package/dist/components/Qafka.styles.js +101 -0
- package/dist/components/Qafka.types.d.ts +744 -0
- package/dist/components/Qafka.types.js +2 -0
- package/dist/components/Qafka.utils.d.ts +7 -0
- package/dist/components/Qafka.utils.js +34 -0
- package/dist/components/QafkaProvider.d.ts +12 -0
- package/dist/components/QafkaProvider.js +87 -0
- package/dist/components/QuickReplies.d.ts +14 -0
- package/dist/components/QuickReplies.js +48 -0
- package/dist/components/StepProgressIndicator.d.ts +12 -0
- package/dist/components/StepProgressIndicator.js +48 -0
- package/dist/components/SuggestionButton.d.ts +42 -0
- package/dist/components/SuggestionButton.js +67 -0
- package/dist/components/ToolStatusPill.d.ts +20 -0
- package/dist/components/ToolStatusPill.js +43 -0
- package/dist/components/TypingIndicator.d.ts +28 -0
- package/dist/components/TypingIndicator.js +109 -0
- package/dist/components/VoicePage.d.ts +48 -0
- package/dist/components/VoicePage.js +683 -0
- package/dist/components/defaults/DefaultCard.d.ts +14 -0
- package/dist/components/defaults/DefaultCard.js +156 -0
- package/dist/components/defaults/DefaultDetail.d.ts +14 -0
- package/dist/components/defaults/DefaultDetail.js +138 -0
- package/dist/components/defaults/DefaultList.d.ts +12 -0
- package/dist/components/defaults/DefaultList.js +98 -0
- package/dist/components/defaults/DefaultTable.d.ts +14 -0
- package/dist/components/defaults/DefaultTable.js +204 -0
- package/dist/components/defaults/index.d.ts +14 -0
- package/dist/components/defaults/index.js +25 -0
- package/dist/components/index.d.ts +22 -0
- package/dist/components/index.js +36 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +13 -0
- package/dist/hooks/useChatMessages.d.ts +72 -0
- package/dist/hooks/useChatMessages.js +505 -0
- package/dist/hooks/useContextManager.d.ts +12 -0
- package/dist/hooks/useContextManager.js +46 -0
- package/dist/hooks/useProjectTheme.d.ts +19 -0
- package/dist/hooks/useProjectTheme.js +163 -0
- package/dist/hooks/useSDK.d.ts +31 -0
- package/dist/hooks/useSDK.js +103 -0
- package/dist/hooks/useVoiceChat.d.ts +110 -0
- package/dist/hooks/useVoiceChat.js +436 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +59 -0
- package/dist/native/QafkaAttestation.d.ts +23 -0
- package/dist/native/QafkaAttestation.js +70 -0
- package/dist/native/QafkaAudio.d.ts +14 -0
- package/dist/native/QafkaAudio.js +31 -0
- package/dist/native/QafkaClipboard.d.ts +11 -0
- package/dist/native/QafkaClipboard.js +14 -0
- package/dist/native/QafkaStorage.d.ts +15 -0
- package/dist/native/QafkaStorage.js +12 -0
- package/dist/resolve-project-config.d.ts +35 -0
- package/dist/resolve-project-config.js +41 -0
- package/dist/runtime-config-loader.d.ts +37 -0
- package/dist/runtime-config-loader.js +53 -0
- package/dist/services/AttestationManager.d.ts +38 -0
- package/dist/services/AttestationManager.js +296 -0
- package/dist/services/BackendService.d.ts +156 -0
- package/dist/services/BackendService.js +755 -0
- package/dist/services/ConversationManager.d.ts +43 -0
- package/dist/services/ConversationManager.js +96 -0
- package/dist/services/NavigationHandler.d.ts +29 -0
- package/dist/services/NavigationHandler.js +70 -0
- package/dist/services/RealtimeService.d.ts +83 -0
- package/dist/services/RealtimeService.js +203 -0
- package/dist/services/storage.d.ts +11 -0
- package/dist/services/storage.js +15 -0
- package/dist/services/storageCore.d.ts +17 -0
- package/dist/services/storageCore.js +46 -0
- package/dist/themes/dark.d.ts +5 -0
- package/dist/themes/dark.js +129 -0
- package/dist/themes/index.d.ts +12 -0
- package/dist/themes/index.js +33 -0
- package/dist/themes/light.d.ts +5 -0
- package/dist/themes/light.js +129 -0
- package/dist/themes/types.d.ts +155 -0
- package/dist/themes/types.js +5 -0
- package/dist/types/chat.d.ts +126 -0
- package/dist/types/chat.js +5 -0
- package/dist/types/components.d.ts +56 -0
- package/dist/types/components.js +16 -0
- package/dist/types/external-navigation.d.ts +19 -0
- package/dist/types/external-navigation.js +8 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.js +25 -0
- package/dist/types/navigation.d.ts +86 -0
- package/dist/types/navigation.js +5 -0
- package/dist/types/sdk.d.ts +36 -0
- package/dist/types/sdk.js +5 -0
- package/dist/utils/deepMerge.d.ts +46 -0
- package/dist/utils/deepMerge.js +70 -0
- package/dist/utils/fontUtils.d.ts +8 -0
- package/dist/utils/fontUtils.js +16 -0
- package/dist/validate-end-user.d.ts +18 -0
- package/dist/validate-end-user.js +74 -0
- package/expo-plugin/withQafkaAttestation.js +57 -0
- package/ios/QafkaAttestation.m +25 -0
- package/ios/QafkaAttestation.swift +128 -0
- package/ios/QafkaAudio.m +23 -0
- package/ios/QafkaAudio.swift +519 -0
- package/ios/QafkaClipboard.m +10 -0
- package/ios/QafkaClipboard.swift +21 -0
- package/ios/QafkaReactImports.h +2 -0
- package/ios/QafkaStorage.m +26 -0
- package/ios/QafkaStorage.swift +118 -0
- package/package.json +82 -0
- package/qafka.config.d.ts +9 -0
- package/qafka.config.js +9 -0
- package/react-native-qafka.podspec +28 -0
- package/react-native.config.js +14 -0
|
@@ -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 {};
|