@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,277 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ /**
3
+ * LinguChat Component
4
+ * Full-page chat interface with back navigation
5
+ * Now with theme support and improved styling
6
+ */
7
+
8
+ import React, { useState, useEffect, useRef } from 'react';
9
+ import { View, TouchableOpacity, StyleSheet, Animated, SafeAreaView, Text } from 'react-native';
10
+ import { NativeChatUI } from './NativeChatUI';
11
+ import { LinguProvider, useLinguContext } from '../context';
12
+ import { useTheme } from '../theme';
13
+ import { scaleIn, pulse } from '../utils/animations';
14
+ /**
15
+ * Internal component that uses context
16
+ */
17
+ const LinguChatInner = props => {
18
+ var _props$showBackButton;
19
+ const {
20
+ theme
21
+ } = useTheme();
22
+ const [isOpen, setIsOpen] = useState(props.autoOpen || false);
23
+ const [hasUnread, setHasUnread] = useState(false);
24
+ const scaleAnim = useRef(new Animated.Value(0)).current;
25
+ const badgePulse = useRef(new Animated.Value(1)).current;
26
+ const {
27
+ messages,
28
+ isLoading,
29
+ config,
30
+ sendMessage,
31
+ startSession,
32
+ endSession,
33
+ isSessionActive
34
+ } = useLinguContext();
35
+
36
+ // Entrance animation for FAB
37
+ useEffect(() => {
38
+ scaleIn(scaleAnim).start();
39
+ }, []);
40
+
41
+ // Pulse animation for unread badge
42
+ useEffect(() => {
43
+ if (hasUnread) {
44
+ pulse(badgePulse).start();
45
+ } else {
46
+ badgePulse.setValue(1);
47
+ }
48
+ }, [hasUnread]);
49
+
50
+ // Auto-open if configured
51
+ useEffect(() => {
52
+ if (props.autoOpen && !isSessionActive) {
53
+ handleOpen();
54
+ }
55
+ }, [props.autoOpen]);
56
+
57
+ // Mark unread when new message arrives and chat is closed
58
+ useEffect(() => {
59
+ if (!isOpen && messages.length > 0) {
60
+ const lastMessage = messages[messages.length - 1];
61
+ if (lastMessage.sender === 'bot') {
62
+ setHasUnread(true);
63
+ }
64
+ }
65
+ }, [messages, isOpen]);
66
+ const handleOpen = async () => {
67
+ setIsOpen(true);
68
+ setHasUnread(false);
69
+ if (!isSessionActive) {
70
+ await startSession();
71
+ }
72
+ };
73
+ const handleClose = async () => {
74
+ var _props$onBackPress;
75
+ setIsOpen(false);
76
+ await endSession();
77
+ (_props$onBackPress = props.onBackPress) === null || _props$onBackPress === void 0 || _props$onBackPress.call(props);
78
+ };
79
+ const handleSendMessage = async text => {
80
+ await sendMessage(text);
81
+ };
82
+ const getPositionStyle = (position = 'bottom-right') => {
83
+ const base = {
84
+ position: 'absolute'
85
+ };
86
+ switch (position) {
87
+ case 'bottom-right':
88
+ return {
89
+ ...base,
90
+ bottom: 20,
91
+ right: 20
92
+ };
93
+ case 'bottom-left':
94
+ return {
95
+ ...base,
96
+ bottom: 20,
97
+ left: 20
98
+ };
99
+ case 'top-right':
100
+ return {
101
+ ...base,
102
+ top: 20,
103
+ right: 20
104
+ };
105
+ case 'top-left':
106
+ return {
107
+ ...base,
108
+ top: 20,
109
+ left: 20
110
+ };
111
+ default:
112
+ return {
113
+ ...base,
114
+ bottom: 20,
115
+ right: 20
116
+ };
117
+ }
118
+ };
119
+ const primaryColor = theme.colors.primary;
120
+ const position = props.position || (config === null || config === void 0 ? void 0 : config.widgetPosition) || 'bottom-right';
121
+ const showBackButton = (_props$showBackButton = props.showBackButton) !== null && _props$showBackButton !== void 0 ? _props$showBackButton : true;
122
+
123
+ // Full-page chat view
124
+ if (isOpen) {
125
+ return /*#__PURE__*/React.createElement(View, {
126
+ style: styles.fullScreenOverlay
127
+ }, /*#__PURE__*/React.createElement(SafeAreaView, {
128
+ style: [styles.fullPageContainer, {
129
+ backgroundColor: theme.colors.background
130
+ }]
131
+ }, showBackButton && /*#__PURE__*/React.createElement(View, {
132
+ style: [styles.header, {
133
+ backgroundColor: primaryColor,
134
+ paddingHorizontal: theme.spacing.lg,
135
+ paddingVertical: theme.spacing.md
136
+ }, theme.shadows.md]
137
+ }, /*#__PURE__*/React.createElement(TouchableOpacity, {
138
+ style: styles.backButton,
139
+ onPress: handleClose,
140
+ activeOpacity: 0.7
141
+ }, /*#__PURE__*/React.createElement(Text, {
142
+ style: styles.backButtonText
143
+ }, "\u2190")), /*#__PURE__*/React.createElement(Text, {
144
+ style: [styles.headerTitle, {
145
+ fontSize: theme.typography.fontSizes.lg,
146
+ fontWeight: theme.typography.fontWeights.semibold
147
+ }]
148
+ }, (config === null || config === void 0 ? void 0 : config.brandName) || 'Lingu Chat'), /*#__PURE__*/React.createElement(View, {
149
+ style: styles.headerSpacer
150
+ })), /*#__PURE__*/React.createElement(NativeChatUI, {
151
+ config: config,
152
+ messages: messages,
153
+ isLoading: isLoading,
154
+ onSendMessage: handleSendMessage
155
+ })));
156
+ }
157
+
158
+ // Floating action button
159
+ return /*#__PURE__*/React.createElement(View, {
160
+ style: [styles.fabContainer, getPositionStyle(position)],
161
+ pointerEvents: "box-none"
162
+ }, /*#__PURE__*/React.createElement(Animated.View, {
163
+ style: {
164
+ transform: [{
165
+ scale: scaleAnim
166
+ }]
167
+ }
168
+ }, /*#__PURE__*/React.createElement(TouchableOpacity, {
169
+ style: [styles.fab, {
170
+ backgroundColor: primaryColor,
171
+ width: 60,
172
+ height: 60,
173
+ borderRadius: 30
174
+ }, theme.shadows.lg],
175
+ onPress: handleOpen,
176
+ activeOpacity: 0.8
177
+ }, hasUnread && /*#__PURE__*/React.createElement(Animated.View, {
178
+ style: [styles.badge, {
179
+ backgroundColor: theme.colors.badge,
180
+ transform: [{
181
+ scale: badgePulse
182
+ }]
183
+ }]
184
+ }), /*#__PURE__*/React.createElement(View, {
185
+ style: styles.icon
186
+ }, /*#__PURE__*/React.createElement(View, {
187
+ style: styles.iconBubble
188
+ })))));
189
+ };
190
+
191
+ /**
192
+ * LinguChat - Main exported component
193
+ * Wraps everything in LinguProvider for standalone state management
194
+ */
195
+ export const LinguChat = ({
196
+ onBackPress,
197
+ showBackButton,
198
+ autoOpen,
199
+ position,
200
+ ...linguConfig
201
+ }) => {
202
+ return /*#__PURE__*/React.createElement(LinguProvider, _extends({}, linguConfig, {
203
+ autoOpen: autoOpen
204
+ }), /*#__PURE__*/React.createElement(LinguChatInner, {
205
+ onBackPress: onBackPress,
206
+ showBackButton: showBackButton,
207
+ autoOpen: autoOpen,
208
+ position: position
209
+ }));
210
+ };
211
+ const styles = StyleSheet.create({
212
+ fullScreenOverlay: {
213
+ position: 'absolute',
214
+ top: 0,
215
+ left: 0,
216
+ right: 0,
217
+ bottom: 0,
218
+ zIndex: 10000
219
+ },
220
+ fullPageContainer: {
221
+ flex: 1
222
+ },
223
+ header: {
224
+ flexDirection: 'row',
225
+ alignItems: 'center',
226
+ justifyContent: 'space-between'
227
+ },
228
+ backButton: {
229
+ width: 40,
230
+ height: 40,
231
+ justifyContent: 'center',
232
+ alignItems: 'center'
233
+ },
234
+ backButtonText: {
235
+ fontSize: 28,
236
+ color: '#fff',
237
+ fontWeight: '600'
238
+ },
239
+ headerTitle: {
240
+ color: '#fff',
241
+ flex: 1,
242
+ textAlign: 'center'
243
+ },
244
+ headerSpacer: {
245
+ width: 40
246
+ },
247
+ fabContainer: {
248
+ zIndex: 9999
249
+ },
250
+ fab: {
251
+ justifyContent: 'center',
252
+ alignItems: 'center'
253
+ },
254
+ badge: {
255
+ position: 'absolute',
256
+ top: 8,
257
+ right: 8,
258
+ width: 12,
259
+ height: 12,
260
+ borderRadius: 6,
261
+ borderWidth: 2,
262
+ borderColor: '#fff'
263
+ },
264
+ icon: {
265
+ width: 30,
266
+ height: 30,
267
+ justifyContent: 'center',
268
+ alignItems: 'center'
269
+ },
270
+ iconBubble: {
271
+ width: 24,
272
+ height: 20,
273
+ backgroundColor: '#fff',
274
+ borderRadius: 12
275
+ }
276
+ });
277
+ //# sourceMappingURL=LinguChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useState","useEffect","useRef","View","TouchableOpacity","StyleSheet","Animated","SafeAreaView","Text","NativeChatUI","LinguProvider","useLinguContext","useTheme","scaleIn","pulse","LinguChatInner","props","_props$showBackButton","theme","isOpen","setIsOpen","autoOpen","hasUnread","setHasUnread","scaleAnim","Value","current","badgePulse","messages","isLoading","config","sendMessage","startSession","endSession","isSessionActive","start","setValue","handleOpen","length","lastMessage","sender","handleClose","_props$onBackPress","onBackPress","call","handleSendMessage","text","getPositionStyle","position","base","bottom","right","left","top","primaryColor","colors","primary","widgetPosition","showBackButton","createElement","style","styles","fullScreenOverlay","fullPageContainer","backgroundColor","background","header","paddingHorizontal","spacing","lg","paddingVertical","md","shadows","backButton","onPress","activeOpacity","backButtonText","headerTitle","fontSize","typography","fontSizes","fontWeight","fontWeights","semibold","brandName","headerSpacer","onSendMessage","fabContainer","pointerEvents","transform","scale","fab","width","height","borderRadius","badge","icon","iconBubble","LinguChat","linguConfig","_extends","create","zIndex","flex","flexDirection","alignItems","justifyContent","color","textAlign","borderWidth","borderColor"],"sources":["LinguChat.tsx"],"sourcesContent":["/**\n * LinguChat Component\n * Full-page chat interface with back navigation\n * Now with theme support and improved styling\n */\n\nimport React, { useState, useEffect, useRef } from 'react';\nimport {\n View,\n TouchableOpacity,\n StyleSheet,\n Animated,\n SafeAreaView,\n Text,\n} from 'react-native';\nimport { NativeChatUI } from './NativeChatUI';\nimport { LinguProvider, useLinguContext } from '../context';\nimport { useTheme } from '../theme';\nimport { scaleIn, pulse } from '../utils/animations';\nimport type { LinguConfig, ChatPosition } from '../types';\n\nexport interface LinguChatProps extends LinguConfig {\n onBackPress?: () => void;\n showBackButton?: boolean;\n position?: ChatPosition; // UI preference for FAB position\n}\n\ninterface LinguChatInnerProps {\n onBackPress?: () => void;\n showBackButton?: boolean;\n autoOpen?: boolean;\n position?: ChatPosition;\n}\n\n/**\n * Internal component that uses context\n */\nconst LinguChatInner: React.FC<LinguChatInnerProps> = (props) => {\n const { theme } = useTheme();\n const [isOpen, setIsOpen] = useState(props.autoOpen || false);\n const [hasUnread, setHasUnread] = useState(false);\n const scaleAnim = useRef(new Animated.Value(0)).current;\n const badgePulse = useRef(new Animated.Value(1)).current;\n\n const {\n messages,\n isLoading,\n config,\n sendMessage,\n startSession,\n endSession,\n isSessionActive,\n } = useLinguContext();\n\n // Entrance animation for FAB\n useEffect(() => {\n scaleIn(scaleAnim).start();\n }, []);\n\n // Pulse animation for unread badge\n useEffect(() => {\n if (hasUnread) {\n pulse(badgePulse).start();\n } else {\n badgePulse.setValue(1);\n }\n }, [hasUnread]);\n\n // Auto-open if configured\n useEffect(() => {\n if (props.autoOpen && !isSessionActive) {\n handleOpen();\n }\n }, [props.autoOpen]);\n\n // Mark unread when new message arrives and chat is closed\n useEffect(() => {\n if (!isOpen && messages.length > 0) {\n const lastMessage = messages[messages.length - 1];\n if (lastMessage.sender === 'bot') {\n setHasUnread(true);\n }\n }\n }, [messages, isOpen]);\n\n const handleOpen = async () => {\n setIsOpen(true);\n setHasUnread(false);\n\n if (!isSessionActive) {\n await startSession();\n }\n };\n\n const handleClose = async () => {\n setIsOpen(false);\n await endSession();\n props.onBackPress?.();\n };\n\n const handleSendMessage = async (text: string) => {\n await sendMessage(text);\n };\n\n const getPositionStyle = (position: ChatPosition = 'bottom-right') => {\n const base = { position: 'absolute' as const };\n switch (position) {\n case 'bottom-right':\n return { ...base, bottom: 20, right: 20 };\n case 'bottom-left':\n return { ...base, bottom: 20, left: 20 };\n case 'top-right':\n return { ...base, top: 20, right: 20 };\n case 'top-left':\n return { ...base, top: 20, left: 20 };\n default:\n return { ...base, bottom: 20, right: 20 };\n }\n };\n\n const primaryColor = theme.colors.primary;\n const position = props.position || config?.widgetPosition || 'bottom-right';\n const showBackButton = props.showBackButton ?? true;\n\n // Full-page chat view\n if (isOpen) {\n return (\n <View style={styles.fullScreenOverlay}>\n <SafeAreaView\n style={[\n styles.fullPageContainer,\n { backgroundColor: theme.colors.background },\n ]}\n >\n {/* Header with back button */}\n {showBackButton && (\n <View\n style={[\n styles.header,\n {\n backgroundColor: primaryColor,\n paddingHorizontal: theme.spacing.lg,\n paddingVertical: theme.spacing.md,\n },\n theme.shadows.md,\n ]}\n >\n <TouchableOpacity\n style={styles.backButton}\n onPress={handleClose}\n activeOpacity={0.7}\n >\n <Text style={styles.backButtonText}>←</Text>\n </TouchableOpacity>\n <Text\n style={[\n styles.headerTitle,\n {\n fontSize: theme.typography.fontSizes.lg,\n fontWeight: theme.typography.fontWeights.semibold,\n },\n ]}\n >\n {config?.brandName || 'Lingu Chat'}\n </Text>\n <View style={styles.headerSpacer} />\n </View>\n )}\n\n {/* Native Chat UI */}\n <NativeChatUI\n config={config}\n messages={messages}\n isLoading={isLoading}\n onSendMessage={handleSendMessage}\n />\n </SafeAreaView>\n </View>\n );\n }\n\n // Floating action button\n return (\n <View style={[styles.fabContainer, getPositionStyle(position)]} pointerEvents=\"box-none\">\n <Animated.View style={{ transform: [{ scale: scaleAnim }] }}>\n <TouchableOpacity\n style={[\n styles.fab,\n {\n backgroundColor: primaryColor,\n width: 60,\n height: 60,\n borderRadius: 30,\n },\n theme.shadows.lg,\n ]}\n onPress={handleOpen}\n activeOpacity={0.8}\n >\n {hasUnread && (\n <Animated.View\n style={[\n styles.badge,\n {\n backgroundColor: theme.colors.badge,\n transform: [{ scale: badgePulse }],\n },\n ]}\n />\n )}\n <View style={styles.icon}>\n {/* Chat icon */}\n <View style={styles.iconBubble} />\n </View>\n </TouchableOpacity>\n </Animated.View>\n </View>\n );\n};\n\n/**\n * LinguChat - Main exported component\n * Wraps everything in LinguProvider for standalone state management\n */\nexport const LinguChat: React.FC<LinguChatProps> = ({\n onBackPress,\n showBackButton,\n autoOpen,\n position,\n ...linguConfig\n}) => {\n return (\n <LinguProvider {...linguConfig} autoOpen={autoOpen}>\n <LinguChatInner\n onBackPress={onBackPress}\n showBackButton={showBackButton}\n autoOpen={autoOpen}\n position={position}\n />\n </LinguProvider>\n );\n};\n\nconst styles = StyleSheet.create({\n fullScreenOverlay: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n zIndex: 10000,\n },\n fullPageContainer: {\n flex: 1,\n },\n header: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n },\n backButton: {\n width: 40,\n height: 40,\n justifyContent: 'center',\n alignItems: 'center',\n },\n backButtonText: {\n fontSize: 28,\n color: '#fff',\n fontWeight: '600',\n },\n headerTitle: {\n color: '#fff',\n flex: 1,\n textAlign: 'center',\n },\n headerSpacer: {\n width: 40,\n },\n fabContainer: {\n zIndex: 9999,\n },\n fab: {\n justifyContent: 'center',\n alignItems: 'center',\n },\n badge: {\n position: 'absolute',\n top: 8,\n right: 8,\n width: 12,\n height: 12,\n borderRadius: 6,\n borderWidth: 2,\n borderColor: '#fff',\n },\n icon: {\n width: 30,\n height: 30,\n justifyContent: 'center',\n alignItems: 'center',\n },\n iconBubble: {\n width: 24,\n height: 20,\n backgroundColor: '#fff',\n borderRadius: 12,\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * LinguWebView Component
3
+ * Wraps the existing web widget in a WebView with native bridge
4
+ * Now with comprehensive logging and message display
5
+ */
6
+
7
+ import React, { useRef, useEffect } from 'react';
8
+ import { WebView } from 'react-native-webview';
9
+ import { StyleSheet } from 'react-native';
10
+ const LOG_PREFIX = '[LinguWebView]';
11
+ export const LinguWebView = ({
12
+ config,
13
+ messages,
14
+ onSendMessage,
15
+ onClose
16
+ }) => {
17
+ const webViewRef = useRef(null);
18
+ console.log(`${LOG_PREFIX} Rendering with ${messages.length} messages`);
19
+
20
+ // Inject messages into WebView when they change
21
+ useEffect(() => {
22
+ if (webViewRef.current && messages.length > 0) {
23
+ console.log(`${LOG_PREFIX} Injecting ${messages.length} messages into WebView`);
24
+ const script = `
25
+ (function() {
26
+ const messagesContainer = document.getElementById('messages');
27
+ if (messagesContainer) {
28
+ messagesContainer.innerHTML = ${JSON.stringify(messages.map(msg => `
29
+ <div style="margin-bottom: 12px; display: flex; justify-content: ${msg.sender === 'user' ? 'flex-end' : 'flex-start'};">
30
+ <div style="
31
+ max-width: 70%;
32
+ padding: 12px;
33
+ border-radius: 12px;
34
+ background: ${msg.sender === 'user' ? '#4ade80' : '#f3f4f6'};
35
+ color: ${msg.sender === 'user' ? 'white' : 'black'};
36
+ ">
37
+ ${msg.text}
38
+ </div>
39
+ </div>
40
+ `).join(''))};
41
+ messagesContainer.scrollTop = messagesContainer.scrollHeight;
42
+ console.log('Messages updated in WebView');
43
+ }
44
+ })();
45
+ true;
46
+ `;
47
+ webViewRef.current.injectJavaScript(script);
48
+ }
49
+ }, [messages]);
50
+
51
+ // Handle messages from WebView
52
+ const handleMessage = event => {
53
+ try {
54
+ const data = JSON.parse(event.nativeEvent.data);
55
+ console.log(`${LOG_PREFIX} Received message from WebView:`, data.type);
56
+ switch (data.type) {
57
+ case 'SEND_MESSAGE':
58
+ console.log(`${LOG_PREFIX} User sent message:`, data.payload.message);
59
+ onSendMessage(data.payload.message);
60
+ break;
61
+ case 'CLOSE_CHAT':
62
+ console.log(`${LOG_PREFIX} User closed chat`);
63
+ onClose();
64
+ break;
65
+ case 'WEBVIEW_LOG':
66
+ console.log(`${LOG_PREFIX} WebView log:`, data.payload);
67
+ break;
68
+ default:
69
+ console.log(`${LOG_PREFIX} Unknown message type:`, data.type);
70
+ }
71
+ } catch (error) {
72
+ console.error(`${LOG_PREFIX} Failed to parse message:`, error);
73
+ }
74
+ };
75
+
76
+ // Generate HTML for the widget
77
+ const generateHTML = () => {
78
+ const configJSON = JSON.stringify(config || {});
79
+ console.log(`${LOG_PREFIX} Generating HTML with config:`, config === null || config === void 0 ? void 0 : config.brandName);
80
+ return `
81
+ <!DOCTYPE html>
82
+ <html>
83
+ <head>
84
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
85
+ <style>
86
+ * {
87
+ margin: 0;
88
+ padding: 0;
89
+ box-sizing: border-box;
90
+ }
91
+ body {
92
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
93
+ overflow: hidden;
94
+ }
95
+ #widget-container {
96
+ width: 100vw;
97
+ height: 100vh;
98
+ display: flex;
99
+ flex-direction: column;
100
+ }
101
+ #messages {
102
+ flex: 1;
103
+ overflow-y: auto;
104
+ padding: 16px;
105
+ background: white;
106
+ }
107
+ #input-container {
108
+ padding: 16px;
109
+ border-top: 1px solid #e5e7eb;
110
+ background: white;
111
+ }
112
+ #message-input {
113
+ width: 100%;
114
+ padding: 12px;
115
+ border: 1px solid #d1d5db;
116
+ border-radius: 8px;
117
+ font-size: 16px;
118
+ }
119
+ </style>
120
+ </head>
121
+ <body>
122
+ <div id="widget-container">
123
+ <div id="messages">
124
+ <div style="text-align: center; color: #9ca3af; padding: 20px;">
125
+ ${(config === null || config === void 0 ? void 0 : config.greetingMessage) || 'Start chatting...'}
126
+ </div>
127
+ </div>
128
+ <div id="input-container">
129
+ <input
130
+ type="text"
131
+ id="message-input"
132
+ placeholder="Type a message..."
133
+ />
134
+ </div>
135
+ </div>
136
+
137
+ <script>
138
+ console.log('WebView initialized');
139
+
140
+ // Configuration from native
141
+ window.linguConfig = ${configJSON};
142
+
143
+ // Bridge to React Native
144
+ window.sendToNative = function(type, payload) {
145
+ console.log('Sending to native:', type, payload);
146
+ window.ReactNativeWebView.postMessage(JSON.stringify({
147
+ type: type,
148
+ payload: payload
149
+ }));
150
+ };
151
+
152
+ // Log to native
153
+ window.logToNative = function(message) {
154
+ window.sendToNative('WEBVIEW_LOG', message);
155
+ };
156
+
157
+ // Handle input
158
+ const input = document.getElementById('message-input');
159
+ input.addEventListener('keypress', function(e) {
160
+ if (e.key === 'Enter' && input.value.trim()) {
161
+ console.log('User pressed enter:', input.value);
162
+ window.sendToNative('SEND_MESSAGE', { message: input.value });
163
+ input.value = '';
164
+ }
165
+ });
166
+
167
+ console.log('Event listeners attached');
168
+ window.logToNative('WebView ready');
169
+ </script>
170
+ </body>
171
+ </html>
172
+ `;
173
+ };
174
+ return /*#__PURE__*/React.createElement(WebView, {
175
+ ref: webViewRef,
176
+ source: {
177
+ html: generateHTML()
178
+ },
179
+ style: styles.webview,
180
+ onMessage: handleMessage,
181
+ javaScriptEnabled: true,
182
+ domStorageEnabled: true,
183
+ startInLoadingState: true,
184
+ scalesPageToFit: true,
185
+ onLoad: () => console.log(`${LOG_PREFIX} WebView loaded`),
186
+ onError: error => console.error(`${LOG_PREFIX} WebView error:`, error)
187
+ });
188
+ };
189
+ const styles = StyleSheet.create({
190
+ webview: {
191
+ flex: 1,
192
+ backgroundColor: 'white'
193
+ }
194
+ });
195
+ //# sourceMappingURL=LinguWebView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useRef","useEffect","WebView","StyleSheet","LOG_PREFIX","LinguWebView","config","messages","onSendMessage","onClose","webViewRef","console","log","length","current","script","JSON","stringify","map","msg","sender","text","join","injectJavaScript","handleMessage","event","data","parse","nativeEvent","type","payload","message","error","generateHTML","configJSON","brandName","greetingMessage","createElement","ref","source","html","style","styles","webview","onMessage","javaScriptEnabled","domStorageEnabled","startInLoadingState","scalesPageToFit","onLoad","onError","create","flex","backgroundColor"],"sources":["LinguWebView.tsx"],"sourcesContent":["/**\n * LinguWebView Component\n * Wraps the existing web widget in a WebView with native bridge\n * Now with comprehensive logging and message display\n */\n\nimport React, { useRef, useEffect } from 'react';\nimport { WebView, WebViewMessageEvent } from 'react-native-webview';\nimport { StyleSheet } from 'react-native';\nimport type { Message, WidgetConfig } from '../types';\n\nconst LOG_PREFIX = '[LinguWebView]';\n\ninterface LinguWebViewProps {\n config: WidgetConfig | null;\n messages: Message[];\n onSendMessage: (message: string) => void;\n onClose: () => void;\n}\n\nexport const LinguWebView: React.FC<LinguWebViewProps> = ({\n config,\n messages,\n onSendMessage,\n onClose,\n}) => {\n const webViewRef = useRef<WebView>(null);\n\n console.log(`${LOG_PREFIX} Rendering with ${messages.length} messages`);\n\n // Inject messages into WebView when they change\n useEffect(() => {\n if (webViewRef.current && messages.length > 0) {\n console.log(`${LOG_PREFIX} Injecting ${messages.length} messages into WebView`);\n const script = `\n (function() {\n const messagesContainer = document.getElementById('messages');\n if (messagesContainer) {\n messagesContainer.innerHTML = ${JSON.stringify(\n messages\n .map(\n (msg) => `\n <div style=\"margin-bottom: 12px; display: flex; justify-content: ${msg.sender === 'user' ? 'flex-end' : 'flex-start'\n };\">\n <div style=\"\n max-width: 70%;\n padding: 12px;\n border-radius: 12px;\n background: ${msg.sender === 'user' ? '#4ade80' : '#f3f4f6'};\n color: ${msg.sender === 'user' ? 'white' : 'black'};\n \">\n ${msg.text}\n </div>\n </div>\n `\n )\n .join('')\n )};\n messagesContainer.scrollTop = messagesContainer.scrollHeight;\n console.log('Messages updated in WebView');\n }\n })();\n true;\n `;\n webViewRef.current.injectJavaScript(script);\n }\n }, [messages]);\n\n // Handle messages from WebView\n const handleMessage = (event: WebViewMessageEvent) => {\n try {\n const data = JSON.parse(event.nativeEvent.data);\n console.log(`${LOG_PREFIX} Received message from WebView:`, data.type);\n\n switch (data.type) {\n case 'SEND_MESSAGE':\n console.log(`${LOG_PREFIX} User sent message:`, data.payload.message);\n onSendMessage(data.payload.message);\n break;\n case 'CLOSE_CHAT':\n console.log(`${LOG_PREFIX} User closed chat`);\n onClose();\n break;\n case 'WEBVIEW_LOG':\n console.log(`${LOG_PREFIX} WebView log:`, data.payload);\n break;\n default:\n console.log(`${LOG_PREFIX} Unknown message type:`, data.type);\n }\n } catch (error) {\n console.error(`${LOG_PREFIX} Failed to parse message:`, error);\n }\n };\n\n // Generate HTML for the widget\n const generateHTML = () => {\n const configJSON = JSON.stringify(config || {});\n console.log(`${LOG_PREFIX} Generating HTML with config:`, config?.brandName);\n\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\">\n <style>\n * {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n overflow: hidden;\n }\n #widget-container {\n width: 100vw;\n height: 100vh;\n display: flex;\n flex-direction: column;\n }\n #messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n background: white;\n }\n #input-container {\n padding: 16px;\n border-top: 1px solid #e5e7eb;\n background: white;\n }\n #message-input {\n width: 100%;\n padding: 12px;\n border: 1px solid #d1d5db;\n border-radius: 8px;\n font-size: 16px;\n }\n </style>\n </head>\n <body>\n <div id=\"widget-container\">\n <div id=\"messages\">\n <div style=\"text-align: center; color: #9ca3af; padding: 20px;\">\n ${config?.greetingMessage || 'Start chatting...'}\n </div>\n </div>\n <div id=\"input-container\">\n <input \n type=\"text\" \n id=\"message-input\"\n placeholder=\"Type a message...\"\n />\n </div>\n </div>\n \n <script>\n console.log('WebView initialized');\n \n // Configuration from native\n window.linguConfig = ${configJSON};\n \n // Bridge to React Native\n window.sendToNative = function(type, payload) {\n console.log('Sending to native:', type, payload);\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: type,\n payload: payload\n }));\n };\n \n // Log to native\n window.logToNative = function(message) {\n window.sendToNative('WEBVIEW_LOG', message);\n };\n \n // Handle input\n const input = document.getElementById('message-input');\n input.addEventListener('keypress', function(e) {\n if (e.key === 'Enter' && input.value.trim()) {\n console.log('User pressed enter:', input.value);\n window.sendToNative('SEND_MESSAGE', { message: input.value });\n input.value = '';\n }\n });\n \n console.log('Event listeners attached');\n window.logToNative('WebView ready');\n </script>\n </body>\n </html>\n `;\n };\n\n return (\n <WebView\n ref={webViewRef}\n source={{ html: generateHTML() }}\n style={styles.webview}\n onMessage={handleMessage}\n javaScriptEnabled\n domStorageEnabled\n startInLoadingState\n scalesPageToFit\n onLoad={() => console.log(`${LOG_PREFIX} WebView loaded`)}\n onError={(error) => console.error(`${LOG_PREFIX} WebView error:`, error)}\n />\n );\n};\n\nconst styles = StyleSheet.create({\n webview: {\n flex: 1,\n backgroundColor: 'white',\n },\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Message Bubble Component
3
+ * Displays a single message with animations and styling
4
+ */
5
+
6
+ import React, { useEffect, useRef } from 'react';
7
+ import { View, Text, StyleSheet, Animated } from 'react-native';
8
+ import { useTheme } from '../theme';
9
+ import { formatRelativeTime } from '../utils/formatters';
10
+ import { messageEntrance } from '../utils/animations';
11
+ export const MessageBubble = ({
12
+ message,
13
+ showTimestamp = false
14
+ }) => {
15
+ const {
16
+ theme
17
+ } = useTheme();
18
+ const isUser = message.sender === 'user';
19
+
20
+ // Animation values
21
+ const translateY = useRef(new Animated.Value(20)).current;
22
+ const opacity = useRef(new Animated.Value(0)).current;
23
+ useEffect(() => {
24
+ // Animate message entrance
25
+ messageEntrance(translateY, opacity, theme.animations.normal).start();
26
+ }, []);
27
+ const bubbleStyle = isUser ? {
28
+ backgroundColor: theme.colors.userBubble
29
+ } : {
30
+ backgroundColor: theme.colors.botBubble,
31
+ ...theme.shadows.sm
32
+ };
33
+ const textStyle = {
34
+ color: isUser ? theme.colors.userText : theme.colors.botText
35
+ };
36
+ return /*#__PURE__*/React.createElement(Animated.View, {
37
+ style: [styles.container, isUser ? styles.userContainer : styles.botContainer, {
38
+ opacity,
39
+ transform: [{
40
+ translateY
41
+ }]
42
+ }]
43
+ }, /*#__PURE__*/React.createElement(View, {
44
+ style: [styles.bubble, bubbleStyle, {
45
+ borderRadius: theme.borderRadius.lg,
46
+ borderBottomRightRadius: isUser ? theme.borderRadius.sm : theme.borderRadius.lg,
47
+ borderBottomLeftRadius: isUser ? theme.borderRadius.lg : theme.borderRadius.sm,
48
+ paddingHorizontal: theme.spacing.md,
49
+ paddingVertical: theme.spacing.sm + 2
50
+ }]
51
+ }, /*#__PURE__*/React.createElement(Text, {
52
+ style: [styles.text, textStyle, {
53
+ fontSize: theme.typography.fontSizes.base,
54
+ lineHeight: theme.typography.fontSizes.base * theme.typography.lineHeights.normal
55
+ }]
56
+ }, message.text), showTimestamp && /*#__PURE__*/React.createElement(Text, {
57
+ style: [styles.timestamp, {
58
+ color: isUser ? theme.colors.gray100 : theme.colors.gray500,
59
+ fontSize: theme.typography.fontSizes.xs,
60
+ marginTop: theme.spacing.xs
61
+ }]
62
+ }, formatRelativeTime(message.timestamp))));
63
+ };
64
+ const styles = StyleSheet.create({
65
+ container: {
66
+ marginBottom: 12,
67
+ flexDirection: 'row'
68
+ },
69
+ userContainer: {
70
+ justifyContent: 'flex-end'
71
+ },
72
+ botContainer: {
73
+ justifyContent: 'flex-start'
74
+ },
75
+ bubble: {
76
+ maxWidth: '75%'
77
+ },
78
+ text: {},
79
+ timestamp: {
80
+ fontSize: 11
81
+ }
82
+ });
83
+ //# sourceMappingURL=MessageBubble.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useEffect","useRef","View","Text","StyleSheet","Animated","useTheme","formatRelativeTime","messageEntrance","MessageBubble","message","showTimestamp","theme","isUser","sender","translateY","Value","current","opacity","animations","normal","start","bubbleStyle","backgroundColor","colors","userBubble","botBubble","shadows","sm","textStyle","color","userText","botText","createElement","style","styles","container","userContainer","botContainer","transform","bubble","borderRadius","lg","borderBottomRightRadius","borderBottomLeftRadius","paddingHorizontal","spacing","md","paddingVertical","text","fontSize","typography","fontSizes","base","lineHeight","lineHeights","timestamp","gray100","gray500","xs","marginTop","create","marginBottom","flexDirection","justifyContent","maxWidth"],"sources":["MessageBubble.tsx"],"sourcesContent":["/**\n * Message Bubble Component\n * Displays a single message with animations and styling\n */\n\nimport React, { useEffect, useRef } from 'react';\nimport { View, Text, StyleSheet, Animated } from 'react-native';\nimport { useTheme } from '../theme';\nimport { formatRelativeTime } from '../utils/formatters';\nimport { messageEntrance } from '../utils/animations';\nimport type { Message } from '../types';\n\ninterface MessageBubbleProps {\n message: Message;\n showTimestamp?: boolean;\n}\n\nexport const MessageBubble: React.FC<MessageBubbleProps> = ({\n message,\n showTimestamp = false,\n}) => {\n const { theme } = useTheme();\n const isUser = message.sender === 'user';\n\n // Animation values\n const translateY = useRef(new Animated.Value(20)).current;\n const opacity = useRef(new Animated.Value(0)).current;\n\n useEffect(() => {\n // Animate message entrance\n messageEntrance(translateY, opacity, theme.animations.normal).start();\n }, []);\n\n const bubbleStyle = isUser\n ? {\n backgroundColor: theme.colors.userBubble,\n }\n : {\n backgroundColor: theme.colors.botBubble,\n ...theme.shadows.sm,\n };\n\n const textStyle = {\n color: isUser ? theme.colors.userText : theme.colors.botText,\n };\n\n return (\n <Animated.View\n style={[\n styles.container,\n isUser ? styles.userContainer : styles.botContainer,\n {\n opacity,\n transform: [{ translateY }],\n },\n ]}\n >\n <View\n style={[\n styles.bubble,\n bubbleStyle,\n {\n borderRadius: theme.borderRadius.lg,\n borderBottomRightRadius: isUser ? theme.borderRadius.sm : theme.borderRadius.lg,\n borderBottomLeftRadius: isUser ? theme.borderRadius.lg : theme.borderRadius.sm,\n paddingHorizontal: theme.spacing.md,\n paddingVertical: theme.spacing.sm + 2,\n },\n ]}\n >\n <Text\n style={[\n styles.text,\n textStyle,\n {\n fontSize: theme.typography.fontSizes.base,\n lineHeight: theme.typography.fontSizes.base * theme.typography.lineHeights.normal,\n },\n ]}\n >\n {message.text}\n </Text>\n {showTimestamp && (\n <Text\n style={[\n styles.timestamp,\n {\n color: isUser ? theme.colors.gray100 : theme.colors.gray500,\n fontSize: theme.typography.fontSizes.xs,\n marginTop: theme.spacing.xs,\n },\n ]}\n >\n {formatRelativeTime(message.timestamp)}\n </Text>\n )}\n </View>\n </Animated.View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: {\n marginBottom: 12,\n flexDirection: 'row',\n },\n userContainer: {\n justifyContent: 'flex-end',\n },\n botContainer: {\n justifyContent: 'flex-start',\n },\n bubble: {\n maxWidth: '75%',\n },\n text: {},\n timestamp: {\n fontSize: 11,\n },\n});\n"],"mappings":"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","ignoreList":[]}