@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,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Card schema types — these match the card definitions you author in your
|
|
3
|
+
* Qafka project configuration.
|
|
4
|
+
*/
|
|
5
|
+
export type CardPrimitiveName = "QView" | "QText" | "QImage" | "QIcon" | "QDivider" | "QButton";
|
|
6
|
+
export type CardStyle = Record<string, string | number | undefined>;
|
|
7
|
+
export type FieldName = string;
|
|
8
|
+
export type CardActionType = "external_navigation" | "deep_link" | "suggest_message" | "copy" | "dismiss" | "share" | "tool_trigger";
|
|
9
|
+
export interface ExternalNavigationAction {
|
|
10
|
+
type: "external_navigation";
|
|
11
|
+
channel: string;
|
|
12
|
+
payload?: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface DeepLinkAction {
|
|
15
|
+
type: "deep_link";
|
|
16
|
+
path: string;
|
|
17
|
+
}
|
|
18
|
+
export interface SuggestMessageAction {
|
|
19
|
+
type: "suggest_message";
|
|
20
|
+
text: string;
|
|
21
|
+
}
|
|
22
|
+
export interface CopyAction {
|
|
23
|
+
type: "copy";
|
|
24
|
+
value: string;
|
|
25
|
+
toastMessage?: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DismissAction {
|
|
28
|
+
type: "dismiss";
|
|
29
|
+
}
|
|
30
|
+
export interface ShareAction {
|
|
31
|
+
type: "share";
|
|
32
|
+
text?: string;
|
|
33
|
+
url?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ToolTriggerAction {
|
|
36
|
+
type: "tool_trigger";
|
|
37
|
+
toolName: string;
|
|
38
|
+
params?: Record<string, unknown>;
|
|
39
|
+
ctaDisplayMode?: "user_message" | "silent";
|
|
40
|
+
}
|
|
41
|
+
export type CardAction = ExternalNavigationAction | DeepLinkAction | SuggestMessageAction | CopyAction | DismissAction | ShareAction | ToolTriggerAction;
|
|
42
|
+
export interface ActionConfig {
|
|
43
|
+
action: CardAction;
|
|
44
|
+
requiresConfirmation?: boolean;
|
|
45
|
+
confirmationTitle?: string;
|
|
46
|
+
confirmationMessage?: string;
|
|
47
|
+
}
|
|
48
|
+
export interface CardNodeBase {
|
|
49
|
+
component: CardPrimitiveName;
|
|
50
|
+
fieldName?: FieldName;
|
|
51
|
+
showIf?: FieldName;
|
|
52
|
+
style?: CardStyle;
|
|
53
|
+
children?: CardNode[];
|
|
54
|
+
}
|
|
55
|
+
export interface QViewNode extends CardNodeBase {
|
|
56
|
+
component: "QView";
|
|
57
|
+
direction?: "row" | "column";
|
|
58
|
+
gap?: number;
|
|
59
|
+
padding?: number;
|
|
60
|
+
background?: string;
|
|
61
|
+
borderRadius?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface QTextNode extends CardNodeBase {
|
|
64
|
+
component: "QText";
|
|
65
|
+
variant?: "title" | "body" | "caption";
|
|
66
|
+
align?: "left" | "center" | "right";
|
|
67
|
+
color?: string;
|
|
68
|
+
text?: string;
|
|
69
|
+
/** Cap text to N lines; overflow truncates per `ellipsizeMode`. */
|
|
70
|
+
numberOfLines?: number;
|
|
71
|
+
/** Where to place the ellipsis when truncated. RN default is "tail". */
|
|
72
|
+
ellipsizeMode?: "head" | "middle" | "tail" | "clip";
|
|
73
|
+
}
|
|
74
|
+
export interface QImageNode extends CardNodeBase {
|
|
75
|
+
component: "QImage";
|
|
76
|
+
src?: string;
|
|
77
|
+
srcFieldName?: FieldName;
|
|
78
|
+
aspectRatio?: number;
|
|
79
|
+
fit?: "cover" | "contain" | "stretch";
|
|
80
|
+
}
|
|
81
|
+
export interface QIconNode extends CardNodeBase {
|
|
82
|
+
component: "QIcon";
|
|
83
|
+
name?: string;
|
|
84
|
+
nameFieldName?: FieldName;
|
|
85
|
+
size?: number;
|
|
86
|
+
color?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface QDividerNode extends CardNodeBase {
|
|
89
|
+
component: "QDivider";
|
|
90
|
+
thickness?: number;
|
|
91
|
+
color?: string;
|
|
92
|
+
}
|
|
93
|
+
export interface QButtonNode extends CardNodeBase {
|
|
94
|
+
component: "QButton";
|
|
95
|
+
label?: string;
|
|
96
|
+
labelFieldName?: FieldName;
|
|
97
|
+
variant?: "primary" | "secondary" | "ghost" | "destructive";
|
|
98
|
+
action?: ActionConfig;
|
|
99
|
+
}
|
|
100
|
+
export type CardNode = QViewNode | QTextNode | QImageNode | QIconNode | QDividerNode | QButtonNode;
|
|
101
|
+
export interface CardDefinition {
|
|
102
|
+
schemaVersion: 1;
|
|
103
|
+
root: CardNode;
|
|
104
|
+
}
|
|
105
|
+
export interface CardEnvelope {
|
|
106
|
+
templateId: string;
|
|
107
|
+
templateSlug: string;
|
|
108
|
+
data: Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
export type UITemplateType = "simple" | "card" | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Theme } from '../themes/types';
|
|
3
|
+
interface ActionResultBadgeProps {
|
|
4
|
+
results: Array<{
|
|
5
|
+
actionType: string;
|
|
6
|
+
success: boolean;
|
|
7
|
+
message: string;
|
|
8
|
+
}>;
|
|
9
|
+
theme: Theme;
|
|
10
|
+
}
|
|
11
|
+
export declare function ActionResultBadge({ results, theme }: ActionResultBadgeProps): React.JSX.Element | null;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
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.ActionResultBadge = ActionResultBadge;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
function ActionResultBadge({ results, theme }) {
|
|
10
|
+
if (!results || results.length === 0)
|
|
11
|
+
return null;
|
|
12
|
+
return (<react_native_1.View style={styles.container}>
|
|
13
|
+
{results.map((result, index) => (<react_native_1.View key={index} style={[
|
|
14
|
+
styles.badge,
|
|
15
|
+
{
|
|
16
|
+
backgroundColor: result.success
|
|
17
|
+
? theme.colors.success || '#22c55e'
|
|
18
|
+
: theme.colors.error || '#ef4444',
|
|
19
|
+
borderRadius: theme.borderRadius.sm,
|
|
20
|
+
},
|
|
21
|
+
]}>
|
|
22
|
+
<react_native_1.Text style={styles.icon}>
|
|
23
|
+
{result.success ? '\u2713' : '\u2717'}
|
|
24
|
+
</react_native_1.Text>
|
|
25
|
+
<react_native_1.Text style={[
|
|
26
|
+
styles.text,
|
|
27
|
+
{
|
|
28
|
+
color: '#ffffff',
|
|
29
|
+
fontSize: theme.typography.fontSize.xs,
|
|
30
|
+
},
|
|
31
|
+
]} numberOfLines={1}>
|
|
32
|
+
{result.message}
|
|
33
|
+
</react_native_1.Text>
|
|
34
|
+
</react_native_1.View>))}
|
|
35
|
+
</react_native_1.View>);
|
|
36
|
+
}
|
|
37
|
+
const styles = react_native_1.StyleSheet.create({
|
|
38
|
+
container: {
|
|
39
|
+
flexDirection: 'row',
|
|
40
|
+
flexWrap: 'wrap',
|
|
41
|
+
gap: 4,
|
|
42
|
+
marginTop: 4,
|
|
43
|
+
},
|
|
44
|
+
badge: {
|
|
45
|
+
flexDirection: 'row',
|
|
46
|
+
alignItems: 'center',
|
|
47
|
+
paddingHorizontal: 8,
|
|
48
|
+
paddingVertical: 3,
|
|
49
|
+
gap: 4,
|
|
50
|
+
},
|
|
51
|
+
icon: {
|
|
52
|
+
color: '#ffffff',
|
|
53
|
+
fontSize: 10,
|
|
54
|
+
},
|
|
55
|
+
text: {
|
|
56
|
+
fontWeight: '500',
|
|
57
|
+
},
|
|
58
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { FlatList } from 'react-native';
|
|
3
|
+
import { Theme } from '../themes';
|
|
4
|
+
import { ChatMessage } from '../types/chat';
|
|
5
|
+
import { ComponentRegistry } from '../types/components';
|
|
6
|
+
import { NavigationButtonProps } from './Qafka.types';
|
|
7
|
+
import { ExternalSuggestion } from '../types/external-navigation';
|
|
8
|
+
export interface ChatPageProps {
|
|
9
|
+
messages: ChatMessage[];
|
|
10
|
+
displayMessages: ChatMessage[];
|
|
11
|
+
isTyping: boolean;
|
|
12
|
+
isSending: boolean;
|
|
13
|
+
streamingMessage: string;
|
|
14
|
+
/** active tool status pill for server-managed tool modes */
|
|
15
|
+
toolStatus?: {
|
|
16
|
+
toolKey: string;
|
|
17
|
+
message: string;
|
|
18
|
+
stage: string;
|
|
19
|
+
} | null;
|
|
20
|
+
sdkReady: boolean;
|
|
21
|
+
sdkError: string | null;
|
|
22
|
+
theme: Theme;
|
|
23
|
+
handleSend: (text: string) => void;
|
|
24
|
+
handleActionClick: (action: any) => void;
|
|
25
|
+
handleExternalSuggestionPress: (suggestion: ExternalSuggestion) => void;
|
|
26
|
+
flatListRef: React.RefObject<FlatList<any> | null>;
|
|
27
|
+
placeholder: string;
|
|
28
|
+
maxMessageLength: number;
|
|
29
|
+
showTimestamps: boolean;
|
|
30
|
+
greetingMessage?: string;
|
|
31
|
+
apiGreeting?: string | null;
|
|
32
|
+
isInitialMessageEnabled?: boolean;
|
|
33
|
+
initialMessageText?: string | null;
|
|
34
|
+
componentRegistry: ComponentRegistry;
|
|
35
|
+
onBack?: () => void;
|
|
36
|
+
onClose?: () => void;
|
|
37
|
+
BackComponent?: React.ComponentType<any>;
|
|
38
|
+
CloseComponent?: React.ComponentType<any>;
|
|
39
|
+
NavigationButtonComponent?: React.ComponentType<NavigationButtonProps>;
|
|
40
|
+
/** Card Template host callbacks forwarded to MessageBubble. */
|
|
41
|
+
cardHostCallbacks?: import('../cards/cta/types').CardCTAHostCallbacks;
|
|
42
|
+
cardLifecycle?: import('../cards/cta/types').CardCTALifecycle;
|
|
43
|
+
}
|
|
44
|
+
export declare function ChatPage({ displayMessages, isTyping, isSending, streamingMessage, toolStatus, sdkReady, sdkError, theme, handleSend, handleActionClick, handleExternalSuggestionPress, flatListRef, placeholder, maxMessageLength, showTimestamps, greetingMessage, apiGreeting, isInitialMessageEnabled, initialMessageText, componentRegistry, onBack, onClose, BackComponent, CloseComponent, NavigationButtonComponent, cardHostCallbacks, cardLifecycle, }: ChatPageProps): React.JSX.Element;
|
|
@@ -0,0 +1,84 @@
|
|
|
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.ChatPage = ChatPage;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
const MessageBubble_1 = require("./MessageBubble");
|
|
10
|
+
const InputArea_1 = require("./InputArea");
|
|
11
|
+
const TypingIndicator_1 = require("./TypingIndicator");
|
|
12
|
+
const ToolStatusPill_1 = require("./ToolStatusPill");
|
|
13
|
+
const Qafka_styles_1 = require("./Qafka.styles");
|
|
14
|
+
function ChatPage({ displayMessages, isTyping, isSending, streamingMessage, toolStatus, sdkReady, sdkError, theme, handleSend, handleActionClick, handleExternalSuggestionPress, flatListRef, placeholder, maxMessageLength, showTimestamps, greetingMessage, apiGreeting, isInitialMessageEnabled, initialMessageText, componentRegistry, onBack, onClose, BackComponent, CloseComponent, NavigationButtonComponent, cardHostCallbacks, cardLifecycle, }) {
|
|
15
|
+
const styles = (0, Qafka_styles_1.getWidgetStyles)(theme);
|
|
16
|
+
const renderMessage = ({ item }) => (<MessageBubble_1.MessageBubble message={item.text || item.content} role={item.role === 'system' ? 'assistant' : item.role} timestamp={new Date(item.timestamp)} theme={theme} showTimestamp={showTimestamps} actions={item.actions} onActionPress={handleActionClick} componentRegistry={componentRegistry} toolDefinition={item.toolResponse?.tool} toolResultData={item.toolResponse?.data} NavigationButtonComponent={NavigationButtonComponent} actionResults={item.actionResults} completedSteps={item.completedSteps} externalSuggestions={item.externalSuggestions} onExternalPress={handleExternalSuggestionPress} card={item.card} cardHostCallbacks={cardHostCallbacks} cardLifecycle={cardLifecycle}/>);
|
|
17
|
+
const renderEmpty = () => {
|
|
18
|
+
if (isInitialMessageEnabled && initialMessageText) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// Greeting is only shown when we actually have one (consumer prop or
|
|
22
|
+
// project-config response). The English fallback was removed because it
|
|
23
|
+
// flashed the wrong brand/language during cold-start; the TypingIndicator
|
|
24
|
+
// below carries the "loading" signal instead.
|
|
25
|
+
const finalGreeting = greetingMessage || apiGreeting;
|
|
26
|
+
return (<react_native_1.View style={[styles.emptyStateStyle, { flex: 1 }]}>
|
|
27
|
+
{finalGreeting && (<react_native_1.Text style={styles.emptyStateTextStyle}>{finalGreeting}</react_native_1.Text>)}
|
|
28
|
+
{!sdkReady && (<react_native_1.View style={{ marginTop: 16 }}>
|
|
29
|
+
<TypingIndicator_1.TypingIndicator theme={theme}/>
|
|
30
|
+
</react_native_1.View>)}
|
|
31
|
+
</react_native_1.View>);
|
|
32
|
+
};
|
|
33
|
+
return (<>
|
|
34
|
+
{/* Navigation Buttons */}
|
|
35
|
+
{(onBack || BackComponent || onClose || CloseComponent) && (<react_native_1.View style={[
|
|
36
|
+
{
|
|
37
|
+
paddingHorizontal: 20,
|
|
38
|
+
flexDirection: 'row',
|
|
39
|
+
justifyContent: 'space-between',
|
|
40
|
+
},
|
|
41
|
+
]}>
|
|
42
|
+
{/* Back Button */}
|
|
43
|
+
<react_native_1.View>
|
|
44
|
+
{BackComponent ? (<BackComponent />) : onBack ? (<react_native_1.TouchableOpacity onPress={onBack} style={styles.navButton}>
|
|
45
|
+
<react_native_1.Text style={styles.navButtonText}>{'<'}</react_native_1.Text>
|
|
46
|
+
</react_native_1.TouchableOpacity>) : null}
|
|
47
|
+
</react_native_1.View>
|
|
48
|
+
|
|
49
|
+
{/* Close Button */}
|
|
50
|
+
<react_native_1.View>
|
|
51
|
+
{CloseComponent ? (<CloseComponent />) : onClose ? (<react_native_1.TouchableOpacity onPress={onClose} style={styles.navButton}>
|
|
52
|
+
<react_native_1.Text style={styles.navButtonText}>{'×'}</react_native_1.Text>
|
|
53
|
+
</react_native_1.TouchableOpacity>) : null}
|
|
54
|
+
</react_native_1.View>
|
|
55
|
+
</react_native_1.View>)}
|
|
56
|
+
|
|
57
|
+
{/* Error banner */}
|
|
58
|
+
{sdkError && (<react_native_1.View style={styles.errorStyle}>
|
|
59
|
+
<react_native_1.Text style={styles.errorTextStyle}>{sdkError}</react_native_1.Text>
|
|
60
|
+
</react_native_1.View>)}
|
|
61
|
+
|
|
62
|
+
{/* Message List */}
|
|
63
|
+
<react_native_1.FlatList ref={flatListRef} data={displayMessages} renderItem={renderMessage} keyExtractor={(item) => item.id} style={{ flex: 1, flexGrow: 1, flexShrink: 1 }} contentContainerStyle={styles.messageListStyle} ListEmptyComponent={renderEmpty} showsVerticalScrollIndicator={false} keyboardShouldPersistTaps="handled" onContentSizeChange={() => {
|
|
64
|
+
if (displayMessages.length > 0) {
|
|
65
|
+
flatListRef.current?.scrollToEnd({ animated: true });
|
|
66
|
+
}
|
|
67
|
+
}}/>
|
|
68
|
+
|
|
69
|
+
{/* Typing Indicator */}
|
|
70
|
+
{isTyping && !streamingMessage && (<react_native_1.View style={styles.typingIndicatorContainer}>
|
|
71
|
+
<TypingIndicator_1.TypingIndicator theme={theme}/>
|
|
72
|
+
</react_native_1.View>)}
|
|
73
|
+
|
|
74
|
+
{/* Tool Status Pill (server-managed modes) */}
|
|
75
|
+
{toolStatus && (<react_native_1.View style={{ paddingHorizontal: 8, alignItems: 'flex-start' }}>
|
|
76
|
+
<ToolStatusPill_1.ToolStatusPill message={toolStatus.message} theme={theme}/>
|
|
77
|
+
</react_native_1.View>)}
|
|
78
|
+
|
|
79
|
+
{/* Input Area — hidden until SDK is ready so users can't type a message
|
|
80
|
+
that would be rejected by an un-attested send. TypingIndicator in the
|
|
81
|
+
empty state carries the "still preparing" signal. */}
|
|
82
|
+
{sdkReady && (<InputArea_1.InputArea theme={theme} placeholder={placeholder} onSend={handleSend} isSending={isSending} maxLength={maxMessageLength}/>)}
|
|
83
|
+
</>);
|
|
84
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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.DataChip = DataChip;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
const QafkaClipboard_1 = require("../native/QafkaClipboard");
|
|
40
|
+
function DataChip({ label, value, copyable = true, theme }) {
|
|
41
|
+
const [copied, setCopied] = (0, react_1.useState)(false);
|
|
42
|
+
const onCopy = (0, react_1.useCallback)(async () => {
|
|
43
|
+
try {
|
|
44
|
+
await (0, QafkaClipboard_1.setString)(value);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Clipboard write can fail on locked devices or sandboxed contexts —
|
|
48
|
+
// swallow silently; the visual state below still reflects the attempt.
|
|
49
|
+
}
|
|
50
|
+
setCopied(true);
|
|
51
|
+
setTimeout(() => setCopied(false), 1500);
|
|
52
|
+
}, [value]);
|
|
53
|
+
return (<react_native_1.View style={[styles.row, { backgroundColor: theme?.surface ?? '#f5f5f7' }]}>
|
|
54
|
+
<react_native_1.View style={styles.textCol}>
|
|
55
|
+
<react_native_1.Text style={[styles.label, { color: theme?.muted ?? '#6b7280' }]}>{label}</react_native_1.Text>
|
|
56
|
+
<react_native_1.Text style={[styles.value, { color: theme?.text ?? '#111827' }]} numberOfLines={2}>
|
|
57
|
+
{value}
|
|
58
|
+
</react_native_1.Text>
|
|
59
|
+
</react_native_1.View>
|
|
60
|
+
{copyable ? (<react_native_1.Pressable onPress={onCopy} accessibilityRole="button" accessibilityLabel={`Copy ${label}`} style={({ pressed }) => [styles.copyBtn, pressed && { opacity: 0.6 }]}>
|
|
61
|
+
<react_native_1.Text style={[styles.copyText, { color: theme?.accent ?? '#2563eb' }]}>
|
|
62
|
+
{copied ? '✓' : 'Copy'}
|
|
63
|
+
</react_native_1.Text>
|
|
64
|
+
</react_native_1.Pressable>) : null}
|
|
65
|
+
</react_native_1.View>);
|
|
66
|
+
}
|
|
67
|
+
const styles = react_native_1.StyleSheet.create({
|
|
68
|
+
row: {
|
|
69
|
+
flexDirection: 'row',
|
|
70
|
+
alignItems: 'center',
|
|
71
|
+
padding: 12,
|
|
72
|
+
borderRadius: 12,
|
|
73
|
+
gap: 12,
|
|
74
|
+
},
|
|
75
|
+
textCol: { flex: 1 },
|
|
76
|
+
label: { fontSize: 12, marginBottom: 2 },
|
|
77
|
+
value: { fontSize: 16, fontWeight: '500' },
|
|
78
|
+
copyBtn: { paddingVertical: 6, paddingHorizontal: 10 },
|
|
79
|
+
copyText: { fontSize: 14, fontWeight: '600' },
|
|
80
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DataChipProps } from './DataChip';
|
|
3
|
+
export interface DataChipItem {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
copyable?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DataChipListProps {
|
|
9
|
+
items: DataChipItem[];
|
|
10
|
+
theme?: any;
|
|
11
|
+
ChipComponent?: React.ComponentType<DataChipProps>;
|
|
12
|
+
}
|
|
13
|
+
export declare function DataChipList({ items, theme, ChipComponent }: DataChipListProps): React.JSX.Element | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
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.DataChipList = DataChipList;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_1 = require("react-native");
|
|
9
|
+
const DataChip_1 = require("./DataChip");
|
|
10
|
+
const MAX_CHIPS = 5;
|
|
11
|
+
function DataChipList({ items, theme, ChipComponent = DataChip_1.DataChip }) {
|
|
12
|
+
const visible = items.slice(0, MAX_CHIPS);
|
|
13
|
+
if (visible.length === 0)
|
|
14
|
+
return null;
|
|
15
|
+
return (<react_native_1.View style={styles.col}>
|
|
16
|
+
{visible.map((it, i) => (<ChipComponent key={`${it.label}_${i}`} label={it.label} value={it.value} copyable={it.copyable !== false} theme={theme}/>))}
|
|
17
|
+
</react_native_1.View>);
|
|
18
|
+
}
|
|
19
|
+
const styles = react_native_1.StyleSheet.create({
|
|
20
|
+
col: { gap: 8 },
|
|
21
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Theme } from '../themes';
|
|
3
|
+
interface FloatingButtonProps {
|
|
4
|
+
isOpen: boolean;
|
|
5
|
+
onPress: () => void;
|
|
6
|
+
unreadCount?: number;
|
|
7
|
+
theme: Theme;
|
|
8
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
9
|
+
}
|
|
10
|
+
export declare function FloatingButton({ isOpen, onPress, unreadCount, theme, position, }: FloatingButtonProps): React.JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
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.FloatingButton = FloatingButton;
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const react_native_1 = require("react-native");
|
|
39
|
+
function FloatingButton({ isOpen, onPress, unreadCount = 0, theme, position = 'bottom-right', }) {
|
|
40
|
+
const rotateAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
41
|
+
const scaleAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
42
|
+
(0, react_1.useEffect)(() => {
|
|
43
|
+
// Rotate animation when opening/closing
|
|
44
|
+
react_native_1.Animated.timing(rotateAnim, {
|
|
45
|
+
toValue: isOpen ? 1 : 0,
|
|
46
|
+
duration: 300,
|
|
47
|
+
useNativeDriver: true,
|
|
48
|
+
}).start();
|
|
49
|
+
}, [isOpen, rotateAnim]);
|
|
50
|
+
const handlePress = () => {
|
|
51
|
+
// Scale animation on press
|
|
52
|
+
react_native_1.Animated.sequence([
|
|
53
|
+
react_native_1.Animated.timing(scaleAnim, {
|
|
54
|
+
toValue: 0.9,
|
|
55
|
+
duration: 100,
|
|
56
|
+
useNativeDriver: true,
|
|
57
|
+
}),
|
|
58
|
+
react_native_1.Animated.timing(scaleAnim, {
|
|
59
|
+
toValue: 1,
|
|
60
|
+
duration: 100,
|
|
61
|
+
useNativeDriver: true,
|
|
62
|
+
}),
|
|
63
|
+
]).start();
|
|
64
|
+
onPress();
|
|
65
|
+
};
|
|
66
|
+
const rotation = rotateAnim.interpolate({
|
|
67
|
+
inputRange: [0, 1],
|
|
68
|
+
outputRange: ['0deg', '45deg'],
|
|
69
|
+
});
|
|
70
|
+
const positionStyle = getPositionStyle(position, theme);
|
|
71
|
+
return (<react_native_1.Animated.View style={[
|
|
72
|
+
styles.container,
|
|
73
|
+
positionStyle,
|
|
74
|
+
{
|
|
75
|
+
transform: [{ scale: scaleAnim }],
|
|
76
|
+
},
|
|
77
|
+
]}>
|
|
78
|
+
<react_native_1.TouchableOpacity style={[
|
|
79
|
+
styles.button,
|
|
80
|
+
{
|
|
81
|
+
backgroundColor: theme.colors.primary,
|
|
82
|
+
...react_native_1.Platform.select({
|
|
83
|
+
ios: {
|
|
84
|
+
shadowColor: '#000',
|
|
85
|
+
shadowOffset: { width: 0, height: 4 },
|
|
86
|
+
shadowOpacity: 0.3,
|
|
87
|
+
shadowRadius: 8,
|
|
88
|
+
},
|
|
89
|
+
android: {
|
|
90
|
+
elevation: 8,
|
|
91
|
+
},
|
|
92
|
+
}),
|
|
93
|
+
},
|
|
94
|
+
]} onPress={handlePress} activeOpacity={0.8}>
|
|
95
|
+
<react_native_1.Animated.View style={{ transform: [{ rotate: rotation }] }}>
|
|
96
|
+
{isOpen ? (<react_native_1.Text style={styles.closeIcon}>✕</react_native_1.Text>) : (<react_native_1.Text style={styles.chatIcon}>💬</react_native_1.Text>)}
|
|
97
|
+
</react_native_1.Animated.View>
|
|
98
|
+
|
|
99
|
+
{/* Unread badge */}
|
|
100
|
+
{!isOpen && unreadCount > 0 && (<react_native_1.View style={[
|
|
101
|
+
styles.badge,
|
|
102
|
+
{ backgroundColor: theme.colors.error || '#FF3B30' },
|
|
103
|
+
]}>
|
|
104
|
+
<react_native_1.Text style={styles.badgeText}>
|
|
105
|
+
{unreadCount > 99 ? '99+' : unreadCount}
|
|
106
|
+
</react_native_1.Text>
|
|
107
|
+
</react_native_1.View>)}
|
|
108
|
+
</react_native_1.TouchableOpacity>
|
|
109
|
+
</react_native_1.Animated.View>);
|
|
110
|
+
}
|
|
111
|
+
function getPositionStyle(position, theme) {
|
|
112
|
+
const spacing = theme.spacing.lg;
|
|
113
|
+
switch (position) {
|
|
114
|
+
case 'bottom-right':
|
|
115
|
+
return { bottom: spacing, right: spacing };
|
|
116
|
+
case 'bottom-left':
|
|
117
|
+
return { bottom: spacing, left: spacing };
|
|
118
|
+
case 'top-right':
|
|
119
|
+
return { top: spacing, right: spacing };
|
|
120
|
+
case 'top-left':
|
|
121
|
+
return { top: spacing, left: spacing };
|
|
122
|
+
default:
|
|
123
|
+
return { bottom: spacing, right: spacing };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
const styles = react_native_1.StyleSheet.create({
|
|
127
|
+
container: {
|
|
128
|
+
position: 'absolute',
|
|
129
|
+
zIndex: 9999,
|
|
130
|
+
},
|
|
131
|
+
button: {
|
|
132
|
+
width: 60,
|
|
133
|
+
height: 60,
|
|
134
|
+
borderRadius: 30,
|
|
135
|
+
justifyContent: 'center',
|
|
136
|
+
alignItems: 'center',
|
|
137
|
+
},
|
|
138
|
+
chatIcon: {
|
|
139
|
+
fontSize: 28,
|
|
140
|
+
},
|
|
141
|
+
closeIcon: {
|
|
142
|
+
fontSize: 28,
|
|
143
|
+
color: '#FFFFFF',
|
|
144
|
+
fontWeight: '300',
|
|
145
|
+
},
|
|
146
|
+
badge: {
|
|
147
|
+
position: 'absolute',
|
|
148
|
+
top: -4,
|
|
149
|
+
right: -4,
|
|
150
|
+
minWidth: 20,
|
|
151
|
+
height: 20,
|
|
152
|
+
borderRadius: 10,
|
|
153
|
+
justifyContent: 'center',
|
|
154
|
+
alignItems: 'center',
|
|
155
|
+
paddingHorizontal: 6,
|
|
156
|
+
},
|
|
157
|
+
badgeText: {
|
|
158
|
+
color: '#FFFFFF',
|
|
159
|
+
fontSize: 12,
|
|
160
|
+
fontWeight: '600',
|
|
161
|
+
},
|
|
162
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Theme } from '../themes/types';
|
|
3
|
+
export interface InputAreaProps {
|
|
4
|
+
/**
|
|
5
|
+
* Theme configuration
|
|
6
|
+
*/
|
|
7
|
+
theme: Theme;
|
|
8
|
+
/**
|
|
9
|
+
* Placeholder text
|
|
10
|
+
*/
|
|
11
|
+
placeholder?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Callback when send button is pressed
|
|
14
|
+
*/
|
|
15
|
+
onSend: (message: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Whether sending is in progress
|
|
18
|
+
*/
|
|
19
|
+
isSending?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Maximum character limit
|
|
22
|
+
*/
|
|
23
|
+
maxLength?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Disable input
|
|
26
|
+
*/
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Show character count
|
|
30
|
+
*/
|
|
31
|
+
showCharacterCount?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* InputArea Component
|
|
35
|
+
*
|
|
36
|
+
* Text input area with send button for chat messages.
|
|
37
|
+
*
|
|
38
|
+
* Features:
|
|
39
|
+
* - Multi-line text input
|
|
40
|
+
* - Character limit with counter
|
|
41
|
+
* - Send button with loading state
|
|
42
|
+
* - Auto-disable when empty or sending
|
|
43
|
+
* - Theme support
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* <InputArea
|
|
48
|
+
* theme={lightTheme}
|
|
49
|
+
* placeholder="Type a message..."
|
|
50
|
+
* onSend={(msg) => handleSend(msg)}
|
|
51
|
+
* isSending={loading}
|
|
52
|
+
* maxLength={500}
|
|
53
|
+
* showCharacterCount
|
|
54
|
+
* />
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function InputArea({ theme, placeholder, onSend, isSending, maxLength, disabled, showCharacterCount, }: InputAreaProps): React.JSX.Element;
|