@uselingu/react-native-sdk 0.1.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 (135) hide show
  1. package/README.md +279 -0
  2. package/lib/commonjs/components/LinguChat.js +283 -0
  3. package/lib/commonjs/components/LinguChat.js.map +1 -0
  4. package/lib/commonjs/components/LinguWebView.js +203 -0
  5. package/lib/commonjs/components/LinguWebView.js.map +1 -0
  6. package/lib/commonjs/components/MessageBubble.js +91 -0
  7. package/lib/commonjs/components/MessageBubble.js.map +1 -0
  8. package/lib/commonjs/components/NativeChatUI.js +192 -0
  9. package/lib/commonjs/components/NativeChatUI.js.map +1 -0
  10. package/lib/commonjs/components/TypingIndicator.js +92 -0
  11. package/lib/commonjs/components/TypingIndicator.js.map +1 -0
  12. package/lib/commonjs/context/LinguProvider.js +47 -0
  13. package/lib/commonjs/context/LinguProvider.js.map +1 -0
  14. package/lib/commonjs/context/index.js +17 -0
  15. package/lib/commonjs/context/index.js.map +1 -0
  16. package/lib/commonjs/hooks/useLinguChat.js +295 -0
  17. package/lib/commonjs/hooks/useLinguChat.js.map +1 -0
  18. package/lib/commonjs/index.js +129 -0
  19. package/lib/commonjs/index.js.map +1 -0
  20. package/lib/commonjs/services/LinguAPI.js +196 -0
  21. package/lib/commonjs/services/LinguAPI.js.map +1 -0
  22. package/lib/commonjs/services/SessionManager.js +131 -0
  23. package/lib/commonjs/services/SessionManager.js.map +1 -0
  24. package/lib/commonjs/services/StorageManager.js +116 -0
  25. package/lib/commonjs/services/StorageManager.js.map +1 -0
  26. package/lib/commonjs/theme/ThemeProvider.js +49 -0
  27. package/lib/commonjs/theme/ThemeProvider.js.map +1 -0
  28. package/lib/commonjs/theme/index.js +28 -0
  29. package/lib/commonjs/theme/index.js.map +1 -0
  30. package/lib/commonjs/theme/theme.js +150 -0
  31. package/lib/commonjs/theme/theme.js.map +1 -0
  32. package/lib/commonjs/types/index.js +2 -0
  33. package/lib/commonjs/types/index.js.map +1 -0
  34. package/lib/commonjs/utils/animations.js +118 -0
  35. package/lib/commonjs/utils/animations.js.map +1 -0
  36. package/lib/commonjs/utils/formatters.js +89 -0
  37. package/lib/commonjs/utils/formatters.js.map +1 -0
  38. package/lib/commonjs/utils/index.js +28 -0
  39. package/lib/commonjs/utils/index.js.map +1 -0
  40. package/lib/module/components/LinguChat.js +277 -0
  41. package/lib/module/components/LinguChat.js.map +1 -0
  42. package/lib/module/components/LinguWebView.js +195 -0
  43. package/lib/module/components/LinguWebView.js.map +1 -0
  44. package/lib/module/components/MessageBubble.js +83 -0
  45. package/lib/module/components/MessageBubble.js.map +1 -0
  46. package/lib/module/components/NativeChatUI.js +184 -0
  47. package/lib/module/components/NativeChatUI.js.map +1 -0
  48. package/lib/module/components/TypingIndicator.js +84 -0
  49. package/lib/module/components/TypingIndicator.js.map +1 -0
  50. package/lib/module/context/LinguProvider.js +38 -0
  51. package/lib/module/context/LinguProvider.js.map +1 -0
  52. package/lib/module/context/index.js +6 -0
  53. package/lib/module/context/index.js.map +1 -0
  54. package/lib/module/hooks/useLinguChat.js +288 -0
  55. package/lib/module/hooks/useLinguChat.js.map +1 -0
  56. package/lib/module/index.js +30 -0
  57. package/lib/module/index.js.map +1 -0
  58. package/lib/module/services/LinguAPI.js +190 -0
  59. package/lib/module/services/LinguAPI.js.map +1 -0
  60. package/lib/module/services/SessionManager.js +124 -0
  61. package/lib/module/services/SessionManager.js.map +1 -0
  62. package/lib/module/services/StorageManager.js +108 -0
  63. package/lib/module/services/StorageManager.js.map +1 -0
  64. package/lib/module/theme/ThemeProvider.js +40 -0
  65. package/lib/module/theme/ThemeProvider.js.map +1 -0
  66. package/lib/module/theme/index.js +7 -0
  67. package/lib/module/theme/index.js.map +1 -0
  68. package/lib/module/theme/theme.js +142 -0
  69. package/lib/module/theme/theme.js.map +1 -0
  70. package/lib/module/types/index.js +2 -0
  71. package/lib/module/types/index.js.map +1 -0
  72. package/lib/module/utils/animations.js +106 -0
  73. package/lib/module/utils/animations.js.map +1 -0
  74. package/lib/module/utils/formatters.js +78 -0
  75. package/lib/module/utils/formatters.js.map +1 -0
  76. package/lib/module/utils/index.js +7 -0
  77. package/lib/module/utils/index.js.map +1 -0
  78. package/lib/typescript/components/LinguChat.d.ts +18 -0
  79. package/lib/typescript/components/LinguChat.d.ts.map +1 -0
  80. package/lib/typescript/components/LinguWebView.d.ts +16 -0
  81. package/lib/typescript/components/LinguWebView.d.ts.map +1 -0
  82. package/lib/typescript/components/MessageBubble.d.ts +13 -0
  83. package/lib/typescript/components/MessageBubble.d.ts.map +1 -0
  84. package/lib/typescript/components/NativeChatUI.d.ts +16 -0
  85. package/lib/typescript/components/NativeChatUI.d.ts.map +1 -0
  86. package/lib/typescript/components/TypingIndicator.d.ts +7 -0
  87. package/lib/typescript/components/TypingIndicator.d.ts.map +1 -0
  88. package/lib/typescript/context/LinguProvider.d.ts +32 -0
  89. package/lib/typescript/context/LinguProvider.d.ts.map +1 -0
  90. package/lib/typescript/context/index.d.ts +5 -0
  91. package/lib/typescript/context/index.d.ts.map +1 -0
  92. package/lib/typescript/hooks/useLinguChat.d.ts +18 -0
  93. package/lib/typescript/hooks/useLinguChat.d.ts.map +1 -0
  94. package/lib/typescript/index.d.ts +19 -0
  95. package/lib/typescript/index.d.ts.map +1 -0
  96. package/lib/typescript/services/LinguAPI.d.ts +39 -0
  97. package/lib/typescript/services/LinguAPI.d.ts.map +1 -0
  98. package/lib/typescript/services/SessionManager.d.ts +46 -0
  99. package/lib/typescript/services/SessionManager.d.ts.map +1 -0
  100. package/lib/typescript/services/StorageManager.d.ts +36 -0
  101. package/lib/typescript/services/StorageManager.d.ts.map +1 -0
  102. package/lib/typescript/theme/ThemeProvider.d.ts +23 -0
  103. package/lib/typescript/theme/ThemeProvider.d.ts.map +1 -0
  104. package/lib/typescript/theme/index.d.ts +6 -0
  105. package/lib/typescript/theme/index.d.ts.map +1 -0
  106. package/lib/typescript/theme/theme.d.ts +130 -0
  107. package/lib/typescript/theme/theme.d.ts.map +1 -0
  108. package/lib/typescript/types/index.d.ts +50 -0
  109. package/lib/typescript/types/index.d.ts.map +1 -0
  110. package/lib/typescript/utils/animations.d.ts +34 -0
  111. package/lib/typescript/utils/animations.d.ts.map +1 -0
  112. package/lib/typescript/utils/formatters.d.ts +25 -0
  113. package/lib/typescript/utils/formatters.d.ts.map +1 -0
  114. package/lib/typescript/utils/index.d.ts +6 -0
  115. package/lib/typescript/utils/index.d.ts.map +1 -0
  116. package/package.json +98 -0
  117. package/src/components/LinguChat.tsx +309 -0
  118. package/src/components/LinguWebView.tsx +216 -0
  119. package/src/components/MessageBubble.tsx +120 -0
  120. package/src/components/NativeChatUI.tsx +247 -0
  121. package/src/components/TypingIndicator.tsx +84 -0
  122. package/src/context/LinguProvider.tsx +53 -0
  123. package/src/context/index.ts +5 -0
  124. package/src/hooks/useLinguChat.ts +314 -0
  125. package/src/index.ts +43 -0
  126. package/src/services/LinguAPI.ts +214 -0
  127. package/src/services/SessionManager.ts +131 -0
  128. package/src/services/StorageManager.ts +111 -0
  129. package/src/theme/ThemeProvider.tsx +58 -0
  130. package/src/theme/index.ts +6 -0
  131. package/src/theme/theme.ts +254 -0
  132. package/src/types/index.ts +59 -0
  133. package/src/utils/animations.ts +141 -0
  134. package/src/utils/formatters.ts +80 -0
  135. package/src/utils/index.ts +6 -0
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Native Chat UI Component
3
+ * Pure React Native implementation without WebView
4
+ * Now with theme support and enhanced styling
5
+ */
6
+
7
+ import React, { useState, useRef, useEffect } from 'react';
8
+ import { View, Text, TextInput, TouchableOpacity, FlatList, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';
9
+ import { useTheme } from '../theme';
10
+ import { MessageBubble } from './MessageBubble';
11
+ import { TypingIndicator } from './TypingIndicator';
12
+ const LOG_PREFIX = '[NativeChatUI]';
13
+ export const NativeChatUI = ({
14
+ config,
15
+ messages,
16
+ isLoading,
17
+ onSendMessage
18
+ }) => {
19
+ const {
20
+ theme
21
+ } = useTheme();
22
+ const [inputText, setInputText] = useState('');
23
+ const flatListRef = useRef(null);
24
+ console.log(`${LOG_PREFIX} Rendering with ${messages.length} messages`);
25
+
26
+ // Auto-scroll to bottom when new messages arrive
27
+ useEffect(() => {
28
+ if (messages.length > 0 && flatListRef.current) {
29
+ setTimeout(() => {
30
+ var _flatListRef$current;
31
+ (_flatListRef$current = flatListRef.current) === null || _flatListRef$current === void 0 || _flatListRef$current.scrollToEnd({
32
+ animated: true
33
+ });
34
+ }, 100);
35
+ }
36
+ }, [messages]);
37
+ const handleSend = () => {
38
+ if (inputText.trim()) {
39
+ console.log(`${LOG_PREFIX} Sending message:`, inputText);
40
+ onSendMessage(inputText.trim());
41
+ setInputText('');
42
+ }
43
+ };
44
+ const renderMessage = ({
45
+ item
46
+ }) => {
47
+ return /*#__PURE__*/React.createElement(MessageBubble, {
48
+ message: item,
49
+ showTimestamp: false
50
+ });
51
+ };
52
+ const renderEmpty = () => /*#__PURE__*/React.createElement(View, {
53
+ style: styles.emptyContainer
54
+ }, /*#__PURE__*/React.createElement(Text, {
55
+ style: [styles.greetingText, {
56
+ color: theme.colors.gray500,
57
+ fontSize: theme.typography.fontSizes.base
58
+ }]
59
+ }, (config === null || config === void 0 ? void 0 : config.greetingMessage) || 'Hello! How can I help you today?'));
60
+ const renderFooter = () => {
61
+ if (isLoading) {
62
+ return /*#__PURE__*/React.createElement(TypingIndicator, null);
63
+ }
64
+ return null;
65
+ };
66
+ const charCount = inputText.length;
67
+ const maxChars = 5000;
68
+ const showCharCount = charCount > maxChars * 0.8;
69
+ return /*#__PURE__*/React.createElement(KeyboardAvoidingView, {
70
+ style: [styles.container, {
71
+ backgroundColor: theme.colors.background
72
+ }],
73
+ behavior: Platform.OS === 'ios' ? 'padding' : undefined,
74
+ keyboardVerticalOffset: Platform.OS === 'ios' ? 90 : 0
75
+ }, /*#__PURE__*/React.createElement(FlatList, {
76
+ ref: flatListRef,
77
+ data: messages,
78
+ renderItem: renderMessage,
79
+ keyExtractor: item => item.id,
80
+ contentContainerStyle: [styles.messagesList, {
81
+ padding: theme.spacing.lg
82
+ }],
83
+ ListEmptyComponent: renderEmpty,
84
+ ListFooterComponent: renderFooter,
85
+ showsVerticalScrollIndicator: false
86
+ }), /*#__PURE__*/React.createElement(View, {
87
+ style: [styles.inputContainer, {
88
+ backgroundColor: theme.colors.background,
89
+ borderTopColor: theme.colors.inputBorder,
90
+ padding: theme.spacing.lg
91
+ }]
92
+ }, /*#__PURE__*/React.createElement(TextInput, {
93
+ style: [styles.input, {
94
+ backgroundColor: theme.colors.inputBackground,
95
+ borderColor: theme.colors.inputBorder,
96
+ color: theme.colors.inputText,
97
+ fontSize: theme.typography.fontSizes.base,
98
+ borderRadius: theme.borderRadius.xl,
99
+ paddingHorizontal: theme.spacing.lg,
100
+ paddingVertical: theme.spacing.sm + 2,
101
+ marginRight: theme.spacing.sm
102
+ }],
103
+ value: inputText,
104
+ onChangeText: setInputText,
105
+ placeholder: "Type a message...",
106
+ placeholderTextColor: theme.colors.gray400,
107
+ multiline: true,
108
+ maxLength: maxChars,
109
+ onSubmitEditing: handleSend,
110
+ returnKeyType: "send",
111
+ blurOnSubmit: false
112
+ }), /*#__PURE__*/React.createElement(TouchableOpacity, {
113
+ style: [styles.sendButton, {
114
+ backgroundColor: theme.colors.primary,
115
+ borderRadius: theme.borderRadius.xl,
116
+ paddingHorizontal: theme.spacing.lg,
117
+ paddingVertical: theme.spacing.sm + 2
118
+ }, !inputText.trim() && styles.sendButtonDisabled],
119
+ onPress: handleSend,
120
+ disabled: !inputText.trim() || isLoading
121
+ }, /*#__PURE__*/React.createElement(Text, {
122
+ style: [styles.sendButtonText, {
123
+ fontSize: theme.typography.fontSizes.base,
124
+ fontWeight: theme.typography.fontWeights.semibold
125
+ }]
126
+ }, "Send"))), showCharCount && /*#__PURE__*/React.createElement(View, {
127
+ style: [styles.charCountContainer, {
128
+ paddingHorizontal: theme.spacing.lg
129
+ }]
130
+ }, /*#__PURE__*/React.createElement(Text, {
131
+ style: [styles.charCount, {
132
+ color: charCount >= maxChars ? theme.colors.errorText : theme.colors.gray500,
133
+ fontSize: theme.typography.fontSizes.xs
134
+ }]
135
+ }, charCount, "/", maxChars)));
136
+ };
137
+ const styles = StyleSheet.create({
138
+ container: {
139
+ flex: 1
140
+ },
141
+ messagesList: {
142
+ flexGrow: 1
143
+ },
144
+ emptyContainer: {
145
+ flex: 1,
146
+ justifyContent: 'center',
147
+ alignItems: 'center',
148
+ padding: 32
149
+ },
150
+ greetingText: {
151
+ textAlign: 'center'
152
+ },
153
+ inputContainer: {
154
+ flexDirection: 'row',
155
+ borderTopWidth: 1,
156
+ alignItems: 'flex-end'
157
+ },
158
+ input: {
159
+ flex: 1,
160
+ minHeight: 40,
161
+ maxHeight: 100,
162
+ borderWidth: 1
163
+ },
164
+ sendButton: {
165
+ justifyContent: 'center',
166
+ alignItems: 'center',
167
+ minWidth: 70
168
+ },
169
+ sendButtonDisabled: {
170
+ opacity: 0.5
171
+ },
172
+ sendButtonText: {
173
+ color: '#ffffff'
174
+ },
175
+ charCountContainer: {
176
+ position: 'absolute',
177
+ bottom: 70,
178
+ right: 0
179
+ },
180
+ charCount: {
181
+ textAlign: 'right'
182
+ }
183
+ });
184
+ //# sourceMappingURL=NativeChatUI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useState","useRef","useEffect","View","Text","TextInput","TouchableOpacity","FlatList","StyleSheet","KeyboardAvoidingView","Platform","useTheme","MessageBubble","TypingIndicator","LOG_PREFIX","NativeChatUI","config","messages","isLoading","onSendMessage","theme","inputText","setInputText","flatListRef","console","log","length","current","setTimeout","_flatListRef$current","scrollToEnd","animated","handleSend","trim","renderMessage","item","createElement","message","showTimestamp","renderEmpty","style","styles","emptyContainer","greetingText","color","colors","gray500","fontSize","typography","fontSizes","base","greetingMessage","renderFooter","charCount","maxChars","showCharCount","container","backgroundColor","background","behavior","OS","undefined","keyboardVerticalOffset","ref","data","renderItem","keyExtractor","id","contentContainerStyle","messagesList","padding","spacing","lg","ListEmptyComponent","ListFooterComponent","showsVerticalScrollIndicator","inputContainer","borderTopColor","inputBorder","input","inputBackground","borderColor","borderRadius","xl","paddingHorizontal","paddingVertical","sm","marginRight","value","onChangeText","placeholder","placeholderTextColor","gray400","multiline","maxLength","onSubmitEditing","returnKeyType","blurOnSubmit","sendButton","primary","sendButtonDisabled","onPress","disabled","sendButtonText","fontWeight","fontWeights","semibold","charCountContainer","errorText","xs","create","flex","flexGrow","justifyContent","alignItems","textAlign","flexDirection","borderTopWidth","minHeight","maxHeight","borderWidth","minWidth","opacity","position","bottom","right"],"sources":["NativeChatUI.tsx"],"sourcesContent":["/**\n * Native Chat UI Component\n * Pure React Native implementation without WebView\n * Now with theme support and enhanced styling\n */\n\nimport React, { useState, useRef, useEffect } from 'react';\nimport {\n View,\n Text,\n TextInput,\n TouchableOpacity,\n FlatList,\n StyleSheet,\n KeyboardAvoidingView,\n Platform,\n} from 'react-native';\nimport { useTheme } from '../theme';\nimport { MessageBubble } from './MessageBubble';\nimport { TypingIndicator } from './TypingIndicator';\nimport type { Message, WidgetConfig } from '../types';\n\nconst LOG_PREFIX = '[NativeChatUI]';\n\ninterface NativeChatUIProps {\n config: WidgetConfig | null;\n messages: Message[];\n isLoading: boolean;\n onSendMessage: (message: string) => void;\n}\n\nexport const NativeChatUI: React.FC<NativeChatUIProps> = ({\n config,\n messages,\n isLoading,\n onSendMessage,\n}) => {\n const { theme } = useTheme();\n const [inputText, setInputText] = useState('');\n const flatListRef = useRef<FlatList>(null);\n\n console.log(`${LOG_PREFIX} Rendering with ${messages.length} messages`);\n\n // Auto-scroll to bottom when new messages arrive\n useEffect(() => {\n if (messages.length > 0 && flatListRef.current) {\n setTimeout(() => {\n flatListRef.current?.scrollToEnd({ animated: true });\n }, 100);\n }\n }, [messages]);\n\n const handleSend = () => {\n if (inputText.trim()) {\n console.log(`${LOG_PREFIX} Sending message:`, inputText);\n onSendMessage(inputText.trim());\n setInputText('');\n }\n };\n\n const renderMessage = ({ item }: { item: Message }) => {\n return <MessageBubble message={item} showTimestamp={false} />;\n };\n\n const renderEmpty = () => (\n <View style={styles.emptyContainer}>\n <Text\n style={[\n styles.greetingText,\n {\n color: theme.colors.gray500,\n fontSize: theme.typography.fontSizes.base,\n },\n ]}\n >\n {config?.greetingMessage || 'Hello! How can I help you today?'}\n </Text>\n </View>\n );\n\n const renderFooter = () => {\n if (isLoading) {\n return <TypingIndicator />;\n }\n return null;\n };\n\n const charCount = inputText.length;\n const maxChars = 5000;\n const showCharCount = charCount > maxChars * 0.8;\n\n return (\n <KeyboardAvoidingView\n style={[styles.container, { backgroundColor: theme.colors.background }]}\n behavior={Platform.OS === 'ios' ? 'padding' : undefined}\n keyboardVerticalOffset={Platform.OS === 'ios' ? 90 : 0}\n >\n {/* Messages List */}\n <FlatList\n ref={flatListRef}\n data={messages}\n renderItem={renderMessage}\n keyExtractor={(item) => item.id}\n contentContainerStyle={[\n styles.messagesList,\n { padding: theme.spacing.lg },\n ]}\n ListEmptyComponent={renderEmpty}\n ListFooterComponent={renderFooter}\n showsVerticalScrollIndicator={false}\n />\n\n {/* Input Area */}\n <View\n style={[\n styles.inputContainer,\n {\n backgroundColor: theme.colors.background,\n borderTopColor: theme.colors.inputBorder,\n padding: theme.spacing.lg,\n },\n ]}\n >\n <TextInput\n style={[\n styles.input,\n {\n backgroundColor: theme.colors.inputBackground,\n borderColor: theme.colors.inputBorder,\n color: theme.colors.inputText,\n fontSize: theme.typography.fontSizes.base,\n borderRadius: theme.borderRadius.xl,\n paddingHorizontal: theme.spacing.lg,\n paddingVertical: theme.spacing.sm + 2,\n marginRight: theme.spacing.sm,\n },\n ]}\n value={inputText}\n onChangeText={setInputText}\n placeholder=\"Type a message...\"\n placeholderTextColor={theme.colors.gray400}\n multiline\n maxLength={maxChars}\n onSubmitEditing={handleSend}\n returnKeyType=\"send\"\n blurOnSubmit={false}\n />\n <TouchableOpacity\n style={[\n styles.sendButton,\n {\n backgroundColor: theme.colors.primary,\n borderRadius: theme.borderRadius.xl,\n paddingHorizontal: theme.spacing.lg,\n paddingVertical: theme.spacing.sm + 2,\n },\n !inputText.trim() && styles.sendButtonDisabled,\n ]}\n onPress={handleSend}\n disabled={!inputText.trim() || isLoading}\n >\n <Text\n style={[\n styles.sendButtonText,\n {\n fontSize: theme.typography.fontSizes.base,\n fontWeight: theme.typography.fontWeights.semibold,\n },\n ]}\n >\n Send\n </Text>\n </TouchableOpacity>\n </View>\n\n {/* Character count */}\n {showCharCount && (\n <View\n style={[\n styles.charCountContainer,\n { paddingHorizontal: theme.spacing.lg },\n ]}\n >\n <Text\n style={[\n styles.charCount,\n {\n color: charCount >= maxChars ? theme.colors.errorText : theme.colors.gray500,\n fontSize: theme.typography.fontSizes.xs,\n },\n ]}\n >\n {charCount}/{maxChars}\n </Text>\n </View>\n )}\n </KeyboardAvoidingView>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {\n flex: 1,\n },\n messagesList: {\n flexGrow: 1,\n },\n emptyContainer: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n padding: 32,\n },\n greetingText: {\n textAlign: 'center',\n },\n inputContainer: {\n flexDirection: 'row',\n borderTopWidth: 1,\n alignItems: 'flex-end',\n },\n input: {\n flex: 1,\n minHeight: 40,\n maxHeight: 100,\n borderWidth: 1,\n },\n sendButton: {\n justifyContent: 'center',\n alignItems: 'center',\n minWidth: 70,\n },\n sendButtonDisabled: {\n opacity: 0.5,\n },\n sendButtonText: {\n color: '#ffffff',\n },\n charCountContainer: {\n position: 'absolute',\n bottom: 70,\n right: 0,\n },\n charCount: {\n textAlign: 'right',\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Typing Indicator Component
3
+ * Animated dots to show bot is typing
4
+ */
5
+
6
+ import React, { useEffect, useRef } from 'react';
7
+ import { View, Animated, StyleSheet } from 'react-native';
8
+ import { useTheme } from '../theme';
9
+ import { typingDotAnimation } from '../utils/animations';
10
+ export const TypingIndicator = () => {
11
+ const {
12
+ theme
13
+ } = useTheme();
14
+ const dot1 = useRef(new Animated.Value(0)).current;
15
+ const dot2 = useRef(new Animated.Value(0)).current;
16
+ const dot3 = useRef(new Animated.Value(0)).current;
17
+ useEffect(() => {
18
+ // Start animations with staggered delays
19
+ const anim1 = typingDotAnimation(dot1, 0);
20
+ const anim2 = typingDotAnimation(dot2, 150);
21
+ const anim3 = typingDotAnimation(dot3, 300);
22
+ anim1.start();
23
+ anim2.start();
24
+ anim3.start();
25
+ return () => {
26
+ anim1.stop();
27
+ anim2.stop();
28
+ anim3.stop();
29
+ };
30
+ }, []);
31
+ return /*#__PURE__*/React.createElement(View, {
32
+ style: [styles.container, {
33
+ backgroundColor: theme.colors.botBubble
34
+ }]
35
+ }, /*#__PURE__*/React.createElement(View, {
36
+ style: styles.dotsContainer
37
+ }, /*#__PURE__*/React.createElement(Animated.View, {
38
+ style: [styles.dot, {
39
+ backgroundColor: theme.colors.gray400
40
+ }, {
41
+ transform: [{
42
+ translateY: dot1
43
+ }]
44
+ }]
45
+ }), /*#__PURE__*/React.createElement(Animated.View, {
46
+ style: [styles.dot, {
47
+ backgroundColor: theme.colors.gray400
48
+ }, {
49
+ transform: [{
50
+ translateY: dot2
51
+ }]
52
+ }]
53
+ }), /*#__PURE__*/React.createElement(Animated.View, {
54
+ style: [styles.dot, {
55
+ backgroundColor: theme.colors.gray400
56
+ }, {
57
+ transform: [{
58
+ translateY: dot3
59
+ }]
60
+ }]
61
+ })));
62
+ };
63
+ const styles = StyleSheet.create({
64
+ container: {
65
+ maxWidth: '75%',
66
+ padding: 12,
67
+ borderRadius: 16,
68
+ borderBottomLeftRadius: 4,
69
+ marginBottom: 12
70
+ },
71
+ dotsContainer: {
72
+ flexDirection: 'row',
73
+ alignItems: 'center',
74
+ justifyContent: 'center',
75
+ height: 20
76
+ },
77
+ dot: {
78
+ width: 8,
79
+ height: 8,
80
+ borderRadius: 4,
81
+ marginHorizontal: 3
82
+ }
83
+ });
84
+ //# sourceMappingURL=TypingIndicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useEffect","useRef","View","Animated","StyleSheet","useTheme","typingDotAnimation","TypingIndicator","theme","dot1","Value","current","dot2","dot3","anim1","anim2","anim3","start","stop","createElement","style","styles","container","backgroundColor","colors","botBubble","dotsContainer","dot","gray400","transform","translateY","create","maxWidth","padding","borderRadius","borderBottomLeftRadius","marginBottom","flexDirection","alignItems","justifyContent","height","width","marginHorizontal"],"sources":["TypingIndicator.tsx"],"sourcesContent":["/**\n * Typing Indicator Component\n * Animated dots to show bot is typing\n */\n\nimport React, { useEffect, useRef } from 'react';\nimport { View, Animated, StyleSheet } from 'react-native';\nimport { useTheme } from '../theme';\nimport { typingDotAnimation } from '../utils/animations';\n\nexport const TypingIndicator: React.FC = () => {\n const { theme } = useTheme();\n\n const dot1 = useRef(new Animated.Value(0)).current;\n const dot2 = useRef(new Animated.Value(0)).current;\n const dot3 = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n // Start animations with staggered delays\n const anim1 = typingDotAnimation(dot1, 0);\n const anim2 = typingDotAnimation(dot2, 150);\n const anim3 = typingDotAnimation(dot3, 300);\n\n anim1.start();\n anim2.start();\n anim3.start();\n\n return () => {\n anim1.stop();\n anim2.stop();\n anim3.stop();\n };\n }, []);\n\n return (\n <View style={[styles.container, { backgroundColor: theme.colors.botBubble }]}>\n <View style={styles.dotsContainer}>\n <Animated.View\n style={[\n styles.dot,\n { backgroundColor: theme.colors.gray400 },\n { transform: [{ translateY: dot1 }] },\n ]}\n />\n <Animated.View\n style={[\n styles.dot,\n { backgroundColor: theme.colors.gray400 },\n { transform: [{ translateY: dot2 }] },\n ]}\n />\n <Animated.View\n style={[\n styles.dot,\n { backgroundColor: theme.colors.gray400 },\n { transform: [{ translateY: dot3 }] },\n ]}\n />\n </View>\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {\n maxWidth: '75%',\n padding: 12,\n borderRadius: 16,\n borderBottomLeftRadius: 4,\n marginBottom: 12,\n },\n dotsContainer: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'center',\n height: 20,\n },\n dot: {\n width: 8,\n height: 8,\n borderRadius: 4,\n marginHorizontal: 3,\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Lingu SDK Context Provider
3
+ * Provides standalone state management for the SDK
4
+ * Completely isolated from host application state
5
+ */
6
+
7
+ import React, { createContext, useContext } from 'react';
8
+ import { useLinguChat } from '../hooks/useLinguChat';
9
+ import { ThemeProvider } from '../theme';
10
+ const LinguContext = /*#__PURE__*/createContext(undefined);
11
+ /**
12
+ * LinguProvider - Wraps the SDK with standalone state management
13
+ * This ensures the SDK state is completely isolated from the host app
14
+ */
15
+ export const LinguProvider = ({
16
+ children,
17
+ ...linguConfig
18
+ }) => {
19
+ const chatState = useLinguChat(linguConfig);
20
+ return /*#__PURE__*/React.createElement(LinguContext.Provider, {
21
+ value: chatState
22
+ }, /*#__PURE__*/React.createElement(ThemeProvider, {
23
+ config: chatState.config
24
+ }, children));
25
+ };
26
+
27
+ /**
28
+ * Hook to access Lingu SDK context
29
+ * Must be used within a LinguProvider
30
+ */
31
+ export const useLinguContext = () => {
32
+ const context = useContext(LinguContext);
33
+ if (context === undefined) {
34
+ throw new Error('useLinguContext must be used within a LinguProvider');
35
+ }
36
+ return context;
37
+ };
38
+ //# sourceMappingURL=LinguProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","createContext","useContext","useLinguChat","ThemeProvider","LinguContext","undefined","LinguProvider","children","linguConfig","chatState","createElement","Provider","value","config","useLinguContext","context","Error"],"sources":["LinguProvider.tsx"],"sourcesContent":["/**\n * Lingu SDK Context Provider\n * Provides standalone state management for the SDK\n * Completely isolated from host application state\n */\n\nimport React, { createContext, useContext, ReactNode } from 'react';\nimport { useLinguChat } from '../hooks/useLinguChat';\nimport { ThemeProvider } from '../theme';\nimport type { Message, WidgetConfig, LinguConfig } from '../types';\n\ninterface LinguContextValue {\n messages: Message[];\n isLoading: boolean;\n config: WidgetConfig | null;\n sendMessage: (text: string) => Promise<void>;\n startSession: () => Promise<void>;\n endSession: () => Promise<void>;\n isSessionActive: boolean;\n clearHistory: () => Promise<void>;\n}\n\nconst LinguContext = createContext<LinguContextValue | undefined>(undefined);\n\ninterface LinguProviderProps extends LinguConfig {\n children: ReactNode;\n}\n\n/**\n * LinguProvider - Wraps the SDK with standalone state management\n * This ensures the SDK state is completely isolated from the host app\n */\nexport const LinguProvider: React.FC<LinguProviderProps> = ({ children, ...linguConfig }) => {\n const chatState = useLinguChat(linguConfig);\n\n return (\n <LinguContext.Provider value={chatState}>\n <ThemeProvider config={chatState.config}>{children}</ThemeProvider>\n </LinguContext.Provider>\n );\n};\n\n/**\n * Hook to access Lingu SDK context\n * Must be used within a LinguProvider\n */\nexport const useLinguContext = (): LinguContextValue => {\n const context = useContext(LinguContext);\n if (context === undefined) {\n throw new Error('useLinguContext must be used within a LinguProvider');\n }\n return context;\n};\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAIC,aAAa,EAAEC,UAAU,QAAmB,OAAO;AACnE,SAASC,YAAY,QAAQ,uBAAuB;AACpD,SAASC,aAAa,QAAQ,UAAU;AAcxC,MAAMC,YAAY,gBAAGJ,aAAa,CAAgCK,SAAS,CAAC;AAM5E;AACA;AACA;AACA;AACA,OAAO,MAAMC,aAA2C,GAAGA,CAAC;EAAEC,QAAQ;EAAE,GAAGC;AAAY,CAAC,KAAK;EAC1F,MAAMC,SAAS,GAAGP,YAAY,CAACM,WAAW,CAAC;EAE3C,oBACGT,KAAA,CAAAW,aAAA,CAACN,YAAY,CAACO,QAAQ;IAACC,KAAK,EAAEH;EAAU,gBACrCV,KAAA,CAAAW,aAAA,CAACP,aAAa;IAACU,MAAM,EAAEJ,SAAS,CAACI;EAAO,GAAEN,QAAwB,CAC9C,CAAC;AAE9B,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,MAAMO,eAAe,GAAGA,CAAA,KAAyB;EACrD,MAAMC,OAAO,GAAGd,UAAU,CAACG,YAAY,CAAC;EACxC,IAAIW,OAAO,KAAKV,SAAS,EAAE;IACxB,MAAM,IAAIW,KAAK,CAAC,qDAAqD,CAAC;EACzE;EACA,OAAOD,OAAO;AACjB,CAAC","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Context exports
3
+ */
4
+
5
+ export * from './LinguProvider';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["/**\n * Context exports\n */\n\nexport * from './LinguProvider';\n"],"mappings":"AAAA;AACA;AACA;;AAEA,cAAc,iBAAiB","ignoreList":[]}
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Custom hook for managing Lingu chat state and operations
3
+ * Now with message persistence and comprehensive logging
4
+ */
5
+
6
+ import { useState, useEffect, useCallback, useRef } from 'react';
7
+ import { LinguAPI } from '../services/LinguAPI';
8
+ import { SessionManager } from '../services/SessionManager';
9
+ import { StorageManager } from '../services/StorageManager';
10
+ const LOG_PREFIX = '[useLinguChat]';
11
+ export const useLinguChat = linguConfig => {
12
+ var _linguConfig$apiKey;
13
+ console.log(`${LOG_PREFIX} Initializing hook with config:`, {
14
+ apiKey: ((_linguConfig$apiKey = linguConfig.apiKey) === null || _linguConfig$apiKey === void 0 ? void 0 : _linguConfig$apiKey.substring(0, 20)) + '...',
15
+ baseURL: linguConfig.baseURL,
16
+ autoOpen: linguConfig.autoOpen
17
+ });
18
+ const [messages, setMessages] = useState([]);
19
+ const [isLoading, setIsLoading] = useState(false);
20
+ const [config, setConfig] = useState(null);
21
+ const [isSessionActive, setIsSessionActive] = useState(false);
22
+ const apiRef = useRef(null);
23
+ const sessionManagerRef = useRef(null);
24
+ const currentSessionIdRef = useRef(null);
25
+
26
+ // Initialize API client and session manager
27
+ useEffect(() => {
28
+ console.log(`${LOG_PREFIX} Setting up API client and session manager`);
29
+ const baseURL = linguConfig.baseURL || 'https://api.uselingu.app/api';
30
+ console.log(`${LOG_PREFIX} API Base URL:`, baseURL);
31
+ const api = new LinguAPI(linguConfig.apiKey, baseURL);
32
+ apiRef.current = api;
33
+ const sessionManager = new SessionManager(api, {
34
+ onSessionStart: async sessionId => {
35
+ var _linguConfig$onSessio;
36
+ console.log(`${LOG_PREFIX} ✅ Session started:`, sessionId);
37
+ currentSessionIdRef.current = sessionId;
38
+ setIsSessionActive(true);
39
+
40
+ // Save session ID
41
+ await StorageManager.saveCurrentSessionId(sessionId);
42
+ console.log(`${LOG_PREFIX} Session ID saved to storage`);
43
+
44
+ // Try to load previous messages for this session
45
+ const savedMessages = await StorageManager.loadMessages(sessionId);
46
+ if (savedMessages.length > 0) {
47
+ console.log(`${LOG_PREFIX} Loaded ${savedMessages.length} messages from storage`);
48
+ setMessages(savedMessages);
49
+ } else {
50
+ console.log(`${LOG_PREFIX} No previous messages found for this session`);
51
+ }
52
+ (_linguConfig$onSessio = linguConfig.onSessionStart) === null || _linguConfig$onSessio === void 0 || _linguConfig$onSessio.call(linguConfig, sessionId);
53
+ },
54
+ onSessionEnd: async sessionId => {
55
+ var _linguConfig$onSessio2;
56
+ console.log(`${LOG_PREFIX} Session ending:`, sessionId);
57
+
58
+ // Save messages before ending
59
+ if (messages.length > 0) {
60
+ console.log(`${LOG_PREFIX} Saving ${messages.length} messages before session end`);
61
+ await StorageManager.saveMessages(sessionId, messages);
62
+ }
63
+ currentSessionIdRef.current = null;
64
+ setIsSessionActive(false);
65
+ console.log(`${LOG_PREFIX} ✅ Session ended successfully`);
66
+ (_linguConfig$onSessio2 = linguConfig.onSessionEnd) === null || _linguConfig$onSessio2 === void 0 || _linguConfig$onSessio2.call(linguConfig, sessionId);
67
+ }
68
+ });
69
+ sessionManagerRef.current = sessionManager;
70
+
71
+ // Load widget configuration
72
+ console.log(`${LOG_PREFIX} Fetching widget configuration...`);
73
+ api.getConfig().then(fetchedConfig => {
74
+ var _fetchedConfig$greeti;
75
+ console.log(`${LOG_PREFIX} ✅ Widget config loaded:`, {
76
+ theme: fetchedConfig.theme,
77
+ primaryColor: fetchedConfig.primaryColor,
78
+ brandName: fetchedConfig.brandName,
79
+ greetingMessage: (_fetchedConfig$greeti = fetchedConfig.greetingMessage) === null || _fetchedConfig$greeti === void 0 ? void 0 : _fetchedConfig$greeti.substring(0, 50)
80
+ });
81
+ setConfig(fetchedConfig);
82
+ }).catch(error => {
83
+ console.error(`${LOG_PREFIX} ❌ Failed to load config:`, error);
84
+ });
85
+
86
+ // Try to restore previous session
87
+ console.log(`${LOG_PREFIX} Attempting to restore previous session...`);
88
+ restorePreviousSession();
89
+
90
+ // Cleanup on unmount
91
+ return () => {
92
+ var _sessionManagerRef$cu;
93
+ console.log(`${LOG_PREFIX} Component unmounting, cleaning up...`);
94
+ // Save messages before cleanup
95
+ if (currentSessionIdRef.current && messages.length > 0) {
96
+ console.log(`${LOG_PREFIX} Saving messages on unmount`);
97
+ StorageManager.saveMessages(currentSessionIdRef.current, messages);
98
+ }
99
+ (_sessionManagerRef$cu = sessionManagerRef.current) === null || _sessionManagerRef$cu === void 0 || _sessionManagerRef$cu.cleanup();
100
+ console.log(`${LOG_PREFIX} Cleanup complete`);
101
+ };
102
+ }, [linguConfig.apiKey, linguConfig.baseURL]);
103
+
104
+ // Save messages whenever they change
105
+ useEffect(() => {
106
+ if (currentSessionIdRef.current && messages.length > 0) {
107
+ console.log(`${LOG_PREFIX} Auto-saving ${messages.length} messages`);
108
+ StorageManager.saveMessages(currentSessionIdRef.current, messages);
109
+ }
110
+ }, [messages]);
111
+
112
+ /**
113
+ * Try to restore previous session
114
+ */
115
+ const restorePreviousSession = async () => {
116
+ try {
117
+ const previousSessionId = await StorageManager.getCurrentSessionId();
118
+ if (previousSessionId) {
119
+ console.log(`${LOG_PREFIX} Found previous session:`, previousSessionId);
120
+ const savedMessages = await StorageManager.loadMessages(previousSessionId);
121
+ if (savedMessages.length > 0) {
122
+ console.log(`${LOG_PREFIX} ✅ Restored ${savedMessages.length} messages from previous session`);
123
+ setMessages(savedMessages);
124
+ currentSessionIdRef.current = previousSessionId;
125
+ } else {
126
+ console.log(`${LOG_PREFIX} Previous session had no messages`);
127
+ }
128
+ } else {
129
+ console.log(`${LOG_PREFIX} No previous session found`);
130
+ }
131
+ } catch (error) {
132
+ console.error(`${LOG_PREFIX} ❌ Failed to restore previous session:`, error);
133
+ }
134
+ };
135
+
136
+ /**
137
+ * Start a new chat session
138
+ */
139
+ const startSession = useCallback(async () => {
140
+ if (!sessionManagerRef.current) {
141
+ console.error(`${LOG_PREFIX} ❌ Session manager not initialized`);
142
+ return;
143
+ }
144
+ try {
145
+ console.log(`${LOG_PREFIX} Starting new session...`);
146
+ await sessionManagerRef.current.start();
147
+
148
+ // Add greeting message if configured and no previous messages
149
+ if (config !== null && config !== void 0 && config.greetingMessage && messages.length === 0) {
150
+ console.log(`${LOG_PREFIX} Adding greeting message`);
151
+ const greetingMsg = {
152
+ id: `greeting-${Date.now()}`,
153
+ text: config.greetingMessage,
154
+ sender: 'bot',
155
+ timestamp: new Date()
156
+ };
157
+ setMessages([greetingMsg]);
158
+ }
159
+ } catch (error) {
160
+ console.error(`${LOG_PREFIX} ❌ Failed to start session:`, error);
161
+ }
162
+ }, [config, messages.length]);
163
+
164
+ /**
165
+ * End the current chat session
166
+ */
167
+ const endSession = useCallback(async () => {
168
+ if (!sessionManagerRef.current) {
169
+ console.error(`${LOG_PREFIX} ❌ Session manager not initialized`);
170
+ return;
171
+ }
172
+ try {
173
+ console.log(`${LOG_PREFIX} Ending session...`);
174
+ await sessionManagerRef.current.end();
175
+ // Don't clear messages - they're saved in storage
176
+ console.log(`${LOG_PREFIX} ✅ Session ended, messages preserved`);
177
+ } catch (error) {
178
+ console.error(`${LOG_PREFIX} ❌ Failed to end session:`, error);
179
+ }
180
+ }, []);
181
+
182
+ /**
183
+ * Clear chat history
184
+ */
185
+ const clearHistory = useCallback(async () => {
186
+ console.log(`${LOG_PREFIX} Clearing chat history...`);
187
+ if (currentSessionIdRef.current) {
188
+ await StorageManager.clearMessages(currentSessionIdRef.current);
189
+ console.log(`${LOG_PREFIX} ✅ Storage cleared for session:`, currentSessionIdRef.current);
190
+ }
191
+ setMessages([]);
192
+ console.log(`${LOG_PREFIX} ✅ Messages cleared from state`);
193
+ }, []);
194
+
195
+ /**
196
+ * Send a message to the AI
197
+ */
198
+ const sendMessage = useCallback(async text => {
199
+ var _linguConfig$onMessag;
200
+ if (!apiRef.current || !sessionManagerRef.current) {
201
+ console.error(`${LOG_PREFIX} ❌ API or session manager not initialized`);
202
+ return;
203
+ }
204
+ const sessionId = sessionManagerRef.current.getSessionId();
205
+ if (!sessionId) {
206
+ console.error(`${LOG_PREFIX} ❌ No active session`);
207
+ return;
208
+ }
209
+ console.log(`${LOG_PREFIX} Sending message:`, {
210
+ sessionId,
211
+ messageLength: text.length,
212
+ preview: text.substring(0, 50)
213
+ });
214
+
215
+ // Add user message
216
+ const userMessage = {
217
+ id: `user-${Date.now()}`,
218
+ text,
219
+ sender: 'user',
220
+ timestamp: new Date()
221
+ };
222
+ setMessages(prev => {
223
+ console.log(`${LOG_PREFIX} Adding user message to state (total: ${prev.length + 1})`);
224
+ return [...prev, userMessage];
225
+ });
226
+ (_linguConfig$onMessag = linguConfig.onMessageSent) === null || _linguConfig$onMessag === void 0 || _linguConfig$onMessag.call(linguConfig, text);
227
+
228
+ // Send to API
229
+ setIsLoading(true);
230
+ console.log(`${LOG_PREFIX} Waiting for AI response...`);
231
+ try {
232
+ var _linguConfig$onMessag2;
233
+ const startTime = Date.now();
234
+ const response = await apiRef.current.sendMessage(text, sessionId);
235
+ const duration = Date.now() - startTime;
236
+ console.log(`${LOG_PREFIX} ✅ Received AI response in ${duration}ms:`, {
237
+ responseLength: response.length,
238
+ preview: response.substring(0, 50)
239
+ });
240
+
241
+ // Add bot response
242
+ const botMessage = {
243
+ id: `bot-${Date.now()}`,
244
+ text: response,
245
+ sender: 'bot',
246
+ timestamp: new Date()
247
+ };
248
+ setMessages(prev => {
249
+ console.log(`${LOG_PREFIX} Adding bot message to state (total: ${prev.length + 1})`);
250
+ return [...prev, botMessage];
251
+ });
252
+ (_linguConfig$onMessag2 = linguConfig.onMessageReceived) === null || _linguConfig$onMessag2 === void 0 || _linguConfig$onMessag2.call(linguConfig, response);
253
+ } catch (error) {
254
+ console.error(`${LOG_PREFIX} ❌ Failed to send message:`, error);
255
+
256
+ // Add error message
257
+ const errorMessage = {
258
+ id: `error-${Date.now()}`,
259
+ text: 'Sorry, I encountered an error. Please try again.',
260
+ sender: 'bot',
261
+ timestamp: new Date()
262
+ };
263
+ setMessages(prev => [...prev, errorMessage]);
264
+ console.log(`${LOG_PREFIX} Added error message to state`);
265
+ } finally {
266
+ setIsLoading(false);
267
+ console.log(`${LOG_PREFIX} Message send complete`);
268
+ }
269
+ }, [linguConfig]);
270
+ console.log(`${LOG_PREFIX} Current state:`, {
271
+ messagesCount: messages.length,
272
+ isLoading,
273
+ hasConfig: !!config,
274
+ isSessionActive,
275
+ currentSessionId: currentSessionIdRef.current
276
+ });
277
+ return {
278
+ messages,
279
+ isLoading,
280
+ config,
281
+ sendMessage,
282
+ startSession,
283
+ endSession,
284
+ isSessionActive,
285
+ clearHistory
286
+ };
287
+ };
288
+ //# sourceMappingURL=useLinguChat.js.map