@usechatting/react-native 0.1.1 → 0.1.3
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.
|
@@ -4,18 +4,20 @@ import { useChattingConversation } from "./use-chatting-conversation";
|
|
|
4
4
|
import { styles } from "./chatting-screen-styles";
|
|
5
5
|
export function ChattingConversationScreen(input) {
|
|
6
6
|
const conversation = useChattingConversation(input);
|
|
7
|
-
const title = conversation.siteConfig?.widgetTitle ?? "
|
|
8
|
-
const
|
|
7
|
+
const title = conversation.siteConfig?.widgetTitle ?? "";
|
|
8
|
+
const greeting = conversation.siteConfig?.greetingText?.trim() || "Start a conversation";
|
|
9
|
+
const brandColor = conversation.siteConfig?.brandColor?.trim() || "#2563EB";
|
|
10
|
+
const teamStatus = conversation.siteConfig?.showOnlineStatus !== false && conversation.siteStatus
|
|
9
11
|
? conversation.siteStatus.online
|
|
10
12
|
? "Team is online"
|
|
11
13
|
: "Team is away"
|
|
12
|
-
:
|
|
13
|
-
return (_jsxs(View, { style: styles.screen, children: [_jsxs(View, { style: styles.header, children: [_jsx(Text, { style: styles.title, children: title }), _jsx(Text, { style: styles.subtitle, children:
|
|
14
|
+
: null;
|
|
15
|
+
return (_jsxs(View, { style: styles.screen, children: [_jsxs(View, { style: [styles.header, { backgroundColor: brandColor }], children: [title ? _jsx(Text, { style: styles.title, children: title }) : null, teamStatus ? _jsx(Text, { style: styles.subtitle, children: teamStatus }) : null] }), _jsxs(ScrollView, { style: styles.scroll, contentContainerStyle: styles.content, children: [conversation.errorMessage ? (_jsx(View, { style: styles.banner, children: _jsx(Text, { style: [styles.bannerText, styles.error], children: conversation.errorMessage }) })) : null, conversation.isLoading ? _jsx(ActivityIndicator, { color: brandColor }) : null, !conversation.isLoading && conversation.messages.length === 0 ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: greeting, isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.messages.map((message) => (_jsx(View, { style: styles.row, children: message.sender === "team" ? (_jsxs(_Fragment, { children: [_jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: false, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : (_jsxs(_Fragment, { children: [_jsx(View, { style: styles.spacer }), _jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: true, brandColor: brandColor })] })) }, message.id))), conversation.teamTyping ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: "Team is typing...", isUser: false, subtle: true, brandColor: brandColor }), _jsx(View, { style: styles.spacer })] })) : null, conversation.faqSuggestions?.items.map((item) => (_jsxs(View, { style: styles.faqCard, children: [_jsx(Text, { style: styles.faqTitle, children: item.question }), _jsx(Text, { style: styles.faqText, children: item.answer })] }, item.id))), conversation.faqSuggestions?.fallbackMessage ? (_jsx(Text, { style: styles.meta, children: conversation.faqSuggestions.fallbackMessage })) : null] }), _jsx(View, { style: styles.footer, children: _jsxs(View, { style: styles.composerRow, children: [_jsx(TextInput, { value: conversation.draftMessage, onChangeText: conversation.setDraftMessage, placeholder: "Type a message", multiline: true, style: [styles.input, styles.composer] }), _jsx(TouchableOpacity, { style: [styles.button, styles.sendButton, { backgroundColor: brandColor }], onPress: () => void conversation.sendMessage(), children: _jsx(Text, { style: styles.buttonText, children: conversation.isSending ? "Sending..." : "Send" }) })] }) })] }));
|
|
14
16
|
}
|
|
15
17
|
function Bubble(input) {
|
|
16
18
|
return (_jsx(View, { style: [
|
|
17
19
|
styles.bubble,
|
|
18
|
-
input.isUser ?
|
|
20
|
+
input.isUser ? { backgroundColor: input.brandColor } : styles.teamBubble,
|
|
19
21
|
input.subtle ? styles.typingBubble : null
|
|
20
22
|
], children: _jsx(Text, { style: input.isUser ? styles.userText : styles.teamText, children: input.message }) }));
|
|
21
23
|
}
|
|
@@ -4,10 +4,9 @@ export declare const styles: {
|
|
|
4
4
|
backgroundColor: string;
|
|
5
5
|
};
|
|
6
6
|
header: {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
backgroundColor: string;
|
|
7
|
+
paddingHorizontal: number;
|
|
8
|
+
paddingTop: number;
|
|
9
|
+
paddingBottom: number;
|
|
11
10
|
};
|
|
12
11
|
title: {
|
|
13
12
|
fontSize: number;
|
|
@@ -25,6 +24,7 @@ export declare const styles: {
|
|
|
25
24
|
content: {
|
|
26
25
|
padding: number;
|
|
27
26
|
gap: number;
|
|
27
|
+
flexGrow: number;
|
|
28
28
|
};
|
|
29
29
|
banner: {
|
|
30
30
|
padding: number;
|
|
@@ -55,13 +55,17 @@ export declare const styles: {
|
|
|
55
55
|
paddingHorizontal: number;
|
|
56
56
|
paddingVertical: number;
|
|
57
57
|
};
|
|
58
|
-
userBubble: {
|
|
59
|
-
backgroundColor: string;
|
|
60
|
-
};
|
|
61
58
|
teamBubble: {
|
|
62
59
|
backgroundColor: string;
|
|
63
|
-
|
|
64
|
-
|
|
60
|
+
borderBottomLeftRadius: number;
|
|
61
|
+
shadowColor: string;
|
|
62
|
+
shadowOpacity: number;
|
|
63
|
+
shadowRadius: number;
|
|
64
|
+
shadowOffset: {
|
|
65
|
+
width: number;
|
|
66
|
+
height: number;
|
|
67
|
+
};
|
|
68
|
+
elevation: number;
|
|
65
69
|
};
|
|
66
70
|
typingBubble: {
|
|
67
71
|
opacity: number;
|
|
@@ -100,12 +104,16 @@ export declare const styles: {
|
|
|
100
104
|
color: string;
|
|
101
105
|
};
|
|
102
106
|
footer: {
|
|
103
|
-
gap: number;
|
|
104
107
|
padding: number;
|
|
105
108
|
borderTopWidth: number;
|
|
106
109
|
borderTopColor: string;
|
|
107
110
|
backgroundColor: string;
|
|
108
111
|
};
|
|
112
|
+
composerRow: {
|
|
113
|
+
flexDirection: string;
|
|
114
|
+
alignItems: string;
|
|
115
|
+
gap: number;
|
|
116
|
+
};
|
|
109
117
|
input: {
|
|
110
118
|
borderWidth: number;
|
|
111
119
|
borderColor: string;
|
|
@@ -116,31 +124,25 @@ export declare const styles: {
|
|
|
116
124
|
color: string;
|
|
117
125
|
};
|
|
118
126
|
composer: {
|
|
127
|
+
flex: number;
|
|
119
128
|
minHeight: number;
|
|
120
129
|
maxHeight: number;
|
|
121
130
|
textAlignVertical: string;
|
|
122
131
|
};
|
|
123
|
-
actions: {
|
|
124
|
-
flexDirection: string;
|
|
125
|
-
gap: number;
|
|
126
|
-
};
|
|
127
132
|
button: {
|
|
128
133
|
flex: number;
|
|
129
134
|
borderRadius: number;
|
|
130
135
|
paddingVertical: number;
|
|
131
136
|
alignItems: string;
|
|
132
137
|
justifyContent: string;
|
|
133
|
-
backgroundColor: string;
|
|
134
138
|
};
|
|
135
|
-
|
|
136
|
-
|
|
139
|
+
sendButton: {
|
|
140
|
+
flex: number;
|
|
141
|
+
minHeight: number;
|
|
142
|
+
paddingHorizontal: number;
|
|
137
143
|
};
|
|
138
144
|
buttonText: {
|
|
139
145
|
color: string;
|
|
140
146
|
fontWeight: string;
|
|
141
147
|
};
|
|
142
|
-
secondaryButtonText: {
|
|
143
|
-
color: string;
|
|
144
|
-
fontWeight: string;
|
|
145
|
-
};
|
|
146
148
|
};
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { StyleSheet } from "react-native";
|
|
2
2
|
export const styles = StyleSheet.create({
|
|
3
|
-
screen: { flex: 1, backgroundColor: "#
|
|
4
|
-
header: {
|
|
5
|
-
title: { fontSize:
|
|
6
|
-
subtitle: { marginTop: 4, fontSize:
|
|
3
|
+
screen: { flex: 1, backgroundColor: "#F6F8FB" },
|
|
4
|
+
header: { paddingHorizontal: 18, paddingTop: 18, paddingBottom: 16 },
|
|
5
|
+
title: { fontSize: 19, fontWeight: "700", color: "#FFFFFF" },
|
|
6
|
+
subtitle: { marginTop: 4, fontSize: 13, color: "#DBEAFE" },
|
|
7
7
|
scroll: { flex: 1 },
|
|
8
|
-
content: { padding: 16, gap: 12 },
|
|
8
|
+
content: { padding: 16, gap: 12, flexGrow: 1 },
|
|
9
9
|
banner: { padding: 12, borderRadius: 16, backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0" },
|
|
10
10
|
bannerText: { color: "#334155", fontSize: 14, lineHeight: 20 },
|
|
11
11
|
error: { color: "#B91C1C" },
|
|
12
12
|
row: { flexDirection: "row", alignItems: "flex-end" },
|
|
13
13
|
spacer: { flex: 1, minWidth: 40 },
|
|
14
14
|
bubble: { maxWidth: "78%", borderRadius: 18, paddingHorizontal: 14, paddingVertical: 10 },
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
teamBubble: {
|
|
16
|
+
backgroundColor: "#FFFFFF",
|
|
17
|
+
borderBottomLeftRadius: 6,
|
|
18
|
+
shadowColor: "#0F172A",
|
|
19
|
+
shadowOpacity: 0.08,
|
|
20
|
+
shadowRadius: 10,
|
|
21
|
+
shadowOffset: { width: 0, height: 4 },
|
|
22
|
+
elevation: 2
|
|
23
|
+
},
|
|
17
24
|
typingBubble: { opacity: 0.8 },
|
|
18
25
|
userText: { color: "#FFFFFF", fontSize: 15, lineHeight: 22 },
|
|
19
26
|
teamText: { color: "#0F172A", fontSize: 15, lineHeight: 22 },
|
|
@@ -21,12 +28,11 @@ export const styles = StyleSheet.create({
|
|
|
21
28
|
faqCard: { padding: 12, borderRadius: 14, backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0", gap: 4 },
|
|
22
29
|
faqTitle: { fontSize: 14, fontWeight: "700", color: "#0F172A" },
|
|
23
30
|
faqText: { fontSize: 13, lineHeight: 19, color: "#475569" },
|
|
24
|
-
footer: {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
button: { flex: 1, borderRadius:
|
|
29
|
-
|
|
30
|
-
buttonText: { color: "#FFFFFF", fontWeight: "700" }
|
|
31
|
-
secondaryButtonText: { color: "#2563EB", fontWeight: "700" }
|
|
31
|
+
footer: { padding: 14, borderTopWidth: 1, borderTopColor: "#E2E8F0", backgroundColor: "#FFFFFF" },
|
|
32
|
+
composerRow: { flexDirection: "row", alignItems: "flex-end", gap: 8 },
|
|
33
|
+
input: { borderWidth: 1, borderColor: "#CBD5E1", borderRadius: 20, paddingHorizontal: 14, paddingVertical: 10, backgroundColor: "#F8FAFC", color: "#0F172A" },
|
|
34
|
+
composer: { flex: 1, minHeight: 44, maxHeight: 120, textAlignVertical: "top" },
|
|
35
|
+
button: { flex: 1, borderRadius: 20, paddingVertical: 12, alignItems: "center", justifyContent: "center" },
|
|
36
|
+
sendButton: { flex: 0, minHeight: 44, paddingHorizontal: 18 },
|
|
37
|
+
buttonText: { color: "#FFFFFF", fontWeight: "700" }
|
|
32
38
|
});
|
|
@@ -10,7 +10,7 @@ export function useChattingConversation(input) {
|
|
|
10
10
|
const [emailAddress, setEmailAddress] = useState(input.draftVisitorEmail ?? "");
|
|
11
11
|
const [teamTyping, setTeamTyping] = useState(false);
|
|
12
12
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
13
|
-
const [isLoading, setIsLoading] = useState(
|
|
13
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
14
14
|
const [isSending, setIsSending] = useState(false);
|
|
15
15
|
const [isSavingEmail, setIsSavingEmail] = useState(false);
|
|
16
16
|
const stopSyncRef = useRef(null);
|