@usechatting/react-native 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.
- package/README.md +122 -0
- package/dist/chatting-client-shared.d.ts +13 -0
- package/dist/chatting-client-shared.js +20 -0
- package/dist/chatting-client.d.ts +27 -0
- package/dist/chatting-client.js +147 -0
- package/dist/chatting-conversation-screen.d.ts +9 -0
- package/dist/chatting-conversation-screen.js +21 -0
- package/dist/chatting-hook-helpers.d.ts +20 -0
- package/dist/chatting-hook-helpers.js +83 -0
- package/dist/chatting-live-stream.d.ts +10 -0
- package/dist/chatting-live-stream.js +136 -0
- package/dist/chatting-poller.d.ts +11 -0
- package/dist/chatting-poller.js +41 -0
- package/dist/chatting-push-registration.d.ts +20 -0
- package/dist/chatting-push-registration.js +69 -0
- package/dist/chatting-screen-styles.d.ts +146 -0
- package/dist/chatting-screen-styles.js +32 -0
- package/dist/chatting-session-store.d.ts +3 -0
- package/dist/chatting-session-store.js +34 -0
- package/dist/chatting-transport.d.ts +13 -0
- package/dist/chatting-transport.js +63 -0
- package/dist/chatting-types.d.ts +108 -0
- package/dist/chatting-types.js +1 -0
- package/dist/chatting-utils.d.ts +13 -0
- package/dist/chatting-utils.js +32 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/use-chatting-conversation.d.ts +26 -0
- package/dist/use-chatting-conversation.js +161 -0
- package/package.json +21 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChattingPushRegistrationInput, ChattingSessionState } from "./chatting-types";
|
|
2
|
+
import type { ChattingTransport } from "./chatting-transport";
|
|
3
|
+
export declare function registerChattingPushToken(input: {
|
|
4
|
+
siteId: string;
|
|
5
|
+
state: ChattingSessionState;
|
|
6
|
+
transport: ChattingTransport;
|
|
7
|
+
registration: ChattingPushRegistrationInput;
|
|
8
|
+
}): Promise<ChattingSessionState>;
|
|
9
|
+
export declare function unregisterChattingPushToken(input: {
|
|
10
|
+
siteId: string;
|
|
11
|
+
state: ChattingSessionState;
|
|
12
|
+
transport: ChattingTransport;
|
|
13
|
+
pushToken?: string | null;
|
|
14
|
+
}): Promise<ChattingSessionState>;
|
|
15
|
+
export declare function syncChattingPushToken(input: {
|
|
16
|
+
siteId: string;
|
|
17
|
+
state: ChattingSessionState;
|
|
18
|
+
transport: ChattingTransport;
|
|
19
|
+
}): Promise<ChattingSessionState>;
|
|
20
|
+
export declare function clearConversationPushState(state: ChattingSessionState): ChattingSessionState;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { normalizeText } from "./chatting-utils";
|
|
2
|
+
export async function registerChattingPushToken(input) {
|
|
3
|
+
const pushToken = requirePushToken(input.registration.pushToken);
|
|
4
|
+
const nextState = {
|
|
5
|
+
...input.state,
|
|
6
|
+
pushToken,
|
|
7
|
+
pushPlatform: normalizeText(input.registration.platform),
|
|
8
|
+
pushAppId: normalizeText(input.registration.appId)
|
|
9
|
+
};
|
|
10
|
+
return syncChattingPushToken({
|
|
11
|
+
siteId: input.siteId,
|
|
12
|
+
state: nextState,
|
|
13
|
+
transport: input.transport
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export async function unregisterChattingPushToken(input) {
|
|
17
|
+
const pushToken = normalizeText(input.pushToken) ?? normalizeText(input.state.pushToken);
|
|
18
|
+
if (!pushToken) {
|
|
19
|
+
return clearedPushState(input.state);
|
|
20
|
+
}
|
|
21
|
+
await input.transport.delete("/api/public/mobile-device", {
|
|
22
|
+
siteId: input.siteId,
|
|
23
|
+
sessionId: input.state.sessionId,
|
|
24
|
+
pushToken
|
|
25
|
+
});
|
|
26
|
+
return clearedPushState(input.state);
|
|
27
|
+
}
|
|
28
|
+
export async function syncChattingPushToken(input) {
|
|
29
|
+
const pushToken = normalizeText(input.state.pushToken);
|
|
30
|
+
if (!pushToken || !input.state.conversationId || input.state.pushTokenSyncedConversationId === input.state.conversationId) {
|
|
31
|
+
return input.state;
|
|
32
|
+
}
|
|
33
|
+
await input.transport.post("/api/public/mobile-device", {
|
|
34
|
+
siteId: input.siteId,
|
|
35
|
+
sessionId: input.state.sessionId,
|
|
36
|
+
conversationId: input.state.conversationId,
|
|
37
|
+
pushToken,
|
|
38
|
+
platform: input.state.pushPlatform ?? null,
|
|
39
|
+
appId: input.state.pushAppId ?? null
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
...input.state,
|
|
43
|
+
pushToken,
|
|
44
|
+
pushTokenSyncedConversationId: input.state.conversationId
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function clearConversationPushState(state) {
|
|
48
|
+
return {
|
|
49
|
+
...state,
|
|
50
|
+
conversationId: null,
|
|
51
|
+
pushTokenSyncedConversationId: null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function clearedPushState(state) {
|
|
55
|
+
return {
|
|
56
|
+
...state,
|
|
57
|
+
pushToken: null,
|
|
58
|
+
pushPlatform: null,
|
|
59
|
+
pushAppId: null,
|
|
60
|
+
pushTokenSyncedConversationId: null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function requirePushToken(value) {
|
|
64
|
+
const pushToken = normalizeText(value);
|
|
65
|
+
if (!pushToken) {
|
|
66
|
+
throw new Error("Push token is required.");
|
|
67
|
+
}
|
|
68
|
+
return pushToken;
|
|
69
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
export declare const styles: {
|
|
2
|
+
screen: {
|
|
3
|
+
flex: number;
|
|
4
|
+
backgroundColor: string;
|
|
5
|
+
};
|
|
6
|
+
header: {
|
|
7
|
+
padding: number;
|
|
8
|
+
borderBottomWidth: number;
|
|
9
|
+
borderBottomColor: string;
|
|
10
|
+
backgroundColor: string;
|
|
11
|
+
};
|
|
12
|
+
title: {
|
|
13
|
+
fontSize: number;
|
|
14
|
+
fontWeight: string;
|
|
15
|
+
color: string;
|
|
16
|
+
};
|
|
17
|
+
subtitle: {
|
|
18
|
+
marginTop: number;
|
|
19
|
+
fontSize: number;
|
|
20
|
+
color: string;
|
|
21
|
+
};
|
|
22
|
+
scroll: {
|
|
23
|
+
flex: number;
|
|
24
|
+
};
|
|
25
|
+
content: {
|
|
26
|
+
padding: number;
|
|
27
|
+
gap: number;
|
|
28
|
+
};
|
|
29
|
+
banner: {
|
|
30
|
+
padding: number;
|
|
31
|
+
borderRadius: number;
|
|
32
|
+
backgroundColor: string;
|
|
33
|
+
borderWidth: number;
|
|
34
|
+
borderColor: string;
|
|
35
|
+
};
|
|
36
|
+
bannerText: {
|
|
37
|
+
color: string;
|
|
38
|
+
fontSize: number;
|
|
39
|
+
lineHeight: number;
|
|
40
|
+
};
|
|
41
|
+
error: {
|
|
42
|
+
color: string;
|
|
43
|
+
};
|
|
44
|
+
row: {
|
|
45
|
+
flexDirection: string;
|
|
46
|
+
alignItems: string;
|
|
47
|
+
};
|
|
48
|
+
spacer: {
|
|
49
|
+
flex: number;
|
|
50
|
+
minWidth: number;
|
|
51
|
+
};
|
|
52
|
+
bubble: {
|
|
53
|
+
maxWidth: string;
|
|
54
|
+
borderRadius: number;
|
|
55
|
+
paddingHorizontal: number;
|
|
56
|
+
paddingVertical: number;
|
|
57
|
+
};
|
|
58
|
+
userBubble: {
|
|
59
|
+
backgroundColor: string;
|
|
60
|
+
};
|
|
61
|
+
teamBubble: {
|
|
62
|
+
backgroundColor: string;
|
|
63
|
+
borderWidth: number;
|
|
64
|
+
borderColor: string;
|
|
65
|
+
};
|
|
66
|
+
typingBubble: {
|
|
67
|
+
opacity: number;
|
|
68
|
+
};
|
|
69
|
+
userText: {
|
|
70
|
+
color: string;
|
|
71
|
+
fontSize: number;
|
|
72
|
+
lineHeight: number;
|
|
73
|
+
};
|
|
74
|
+
teamText: {
|
|
75
|
+
color: string;
|
|
76
|
+
fontSize: number;
|
|
77
|
+
lineHeight: number;
|
|
78
|
+
};
|
|
79
|
+
meta: {
|
|
80
|
+
marginTop: number;
|
|
81
|
+
fontSize: number;
|
|
82
|
+
color: string;
|
|
83
|
+
};
|
|
84
|
+
faqCard: {
|
|
85
|
+
padding: number;
|
|
86
|
+
borderRadius: number;
|
|
87
|
+
backgroundColor: string;
|
|
88
|
+
borderWidth: number;
|
|
89
|
+
borderColor: string;
|
|
90
|
+
gap: number;
|
|
91
|
+
};
|
|
92
|
+
faqTitle: {
|
|
93
|
+
fontSize: number;
|
|
94
|
+
fontWeight: string;
|
|
95
|
+
color: string;
|
|
96
|
+
};
|
|
97
|
+
faqText: {
|
|
98
|
+
fontSize: number;
|
|
99
|
+
lineHeight: number;
|
|
100
|
+
color: string;
|
|
101
|
+
};
|
|
102
|
+
footer: {
|
|
103
|
+
gap: number;
|
|
104
|
+
padding: number;
|
|
105
|
+
borderTopWidth: number;
|
|
106
|
+
borderTopColor: string;
|
|
107
|
+
backgroundColor: string;
|
|
108
|
+
};
|
|
109
|
+
input: {
|
|
110
|
+
borderWidth: number;
|
|
111
|
+
borderColor: string;
|
|
112
|
+
borderRadius: number;
|
|
113
|
+
paddingHorizontal: number;
|
|
114
|
+
paddingVertical: number;
|
|
115
|
+
backgroundColor: string;
|
|
116
|
+
color: string;
|
|
117
|
+
};
|
|
118
|
+
composer: {
|
|
119
|
+
minHeight: number;
|
|
120
|
+
maxHeight: number;
|
|
121
|
+
textAlignVertical: string;
|
|
122
|
+
};
|
|
123
|
+
actions: {
|
|
124
|
+
flexDirection: string;
|
|
125
|
+
gap: number;
|
|
126
|
+
};
|
|
127
|
+
button: {
|
|
128
|
+
flex: number;
|
|
129
|
+
borderRadius: number;
|
|
130
|
+
paddingVertical: number;
|
|
131
|
+
alignItems: string;
|
|
132
|
+
justifyContent: string;
|
|
133
|
+
backgroundColor: string;
|
|
134
|
+
};
|
|
135
|
+
secondaryButton: {
|
|
136
|
+
backgroundColor: string;
|
|
137
|
+
};
|
|
138
|
+
buttonText: {
|
|
139
|
+
color: string;
|
|
140
|
+
fontWeight: string;
|
|
141
|
+
};
|
|
142
|
+
secondaryButtonText: {
|
|
143
|
+
color: string;
|
|
144
|
+
fontWeight: string;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
export const styles = StyleSheet.create({
|
|
3
|
+
screen: { flex: 1, backgroundColor: "#F8FAFC" },
|
|
4
|
+
header: { padding: 16, borderBottomWidth: 1, borderBottomColor: "#E2E8F0", backgroundColor: "#FFFFFF" },
|
|
5
|
+
title: { fontSize: 18, fontWeight: "700", color: "#0F172A" },
|
|
6
|
+
subtitle: { marginTop: 4, fontSize: 14, color: "#475569" },
|
|
7
|
+
scroll: { flex: 1 },
|
|
8
|
+
content: { padding: 16, gap: 12 },
|
|
9
|
+
banner: { padding: 12, borderRadius: 16, backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0" },
|
|
10
|
+
bannerText: { color: "#334155", fontSize: 14, lineHeight: 20 },
|
|
11
|
+
error: { color: "#B91C1C" },
|
|
12
|
+
row: { flexDirection: "row", alignItems: "flex-end" },
|
|
13
|
+
spacer: { flex: 1, minWidth: 40 },
|
|
14
|
+
bubble: { maxWidth: "78%", borderRadius: 18, paddingHorizontal: 14, paddingVertical: 10 },
|
|
15
|
+
userBubble: { backgroundColor: "#2563EB" },
|
|
16
|
+
teamBubble: { backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0" },
|
|
17
|
+
typingBubble: { opacity: 0.8 },
|
|
18
|
+
userText: { color: "#FFFFFF", fontSize: 15, lineHeight: 22 },
|
|
19
|
+
teamText: { color: "#0F172A", fontSize: 15, lineHeight: 22 },
|
|
20
|
+
meta: { marginTop: 4, fontSize: 12, color: "#94A3B8" },
|
|
21
|
+
faqCard: { padding: 12, borderRadius: 14, backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0", gap: 4 },
|
|
22
|
+
faqTitle: { fontSize: 14, fontWeight: "700", color: "#0F172A" },
|
|
23
|
+
faqText: { fontSize: 13, lineHeight: 19, color: "#475569" },
|
|
24
|
+
footer: { gap: 12, padding: 16, borderTopWidth: 1, borderTopColor: "#E2E8F0", backgroundColor: "#FFFFFF" },
|
|
25
|
+
input: { borderWidth: 1, borderColor: "#CBD5E1", borderRadius: 14, paddingHorizontal: 12, paddingVertical: 10, backgroundColor: "#FFFFFF", color: "#0F172A" },
|
|
26
|
+
composer: { minHeight: 44, maxHeight: 120, textAlignVertical: "top" },
|
|
27
|
+
actions: { flexDirection: "row", gap: 12 },
|
|
28
|
+
button: { flex: 1, borderRadius: 14, paddingVertical: 12, alignItems: "center", justifyContent: "center", backgroundColor: "#2563EB" },
|
|
29
|
+
secondaryButton: { backgroundColor: "#EFF6FF" },
|
|
30
|
+
buttonText: { color: "#FFFFFF", fontWeight: "700" },
|
|
31
|
+
secondaryButtonText: { color: "#2563EB", fontWeight: "700" }
|
|
32
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ChattingKeyValueStorage, ChattingSessionStore } from "./chatting-types";
|
|
2
|
+
export declare function createMemorySessionStore(): ChattingSessionStore;
|
|
3
|
+
export declare function createKeyValueSessionStore(storage: ChattingKeyValueStorage, namespace: string): ChattingSessionStore;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function createMemorySessionStore() {
|
|
2
|
+
let state = null;
|
|
3
|
+
return {
|
|
4
|
+
async load() {
|
|
5
|
+
return state;
|
|
6
|
+
},
|
|
7
|
+
async save(nextState) {
|
|
8
|
+
state = nextState;
|
|
9
|
+
},
|
|
10
|
+
async clear() {
|
|
11
|
+
state = null;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function createKeyValueSessionStore(storage, namespace) {
|
|
16
|
+
const key = `chatting:${namespace}:session`;
|
|
17
|
+
return {
|
|
18
|
+
async load() {
|
|
19
|
+
const value = await storage.getItem(key);
|
|
20
|
+
return value ? JSON.parse(value) : null;
|
|
21
|
+
},
|
|
22
|
+
async save(state) {
|
|
23
|
+
await storage.setItem(key, JSON.stringify(state));
|
|
24
|
+
},
|
|
25
|
+
async clear() {
|
|
26
|
+
if (typeof storage.removeItem === "function") {
|
|
27
|
+
await storage.removeItem(key);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
await storage.setItem(key, "");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class ChattingTransport {
|
|
2
|
+
private readonly baseURL;
|
|
3
|
+
private readonly fetchImpl;
|
|
4
|
+
constructor(baseURL: string, fetchImpl: typeof fetch);
|
|
5
|
+
get<Response>(path: string, query: Record<string, string | null | undefined>): Promise<Response>;
|
|
6
|
+
post<Response>(path: string, body: Record<string, unknown>): Promise<Response>;
|
|
7
|
+
delete<Response>(path: string, body: Record<string, unknown>): Promise<Response>;
|
|
8
|
+
connectLive(path: string, query: Record<string, string | null | undefined>, input: {
|
|
9
|
+
onEvent(event: unknown): void;
|
|
10
|
+
onDisconnect?(error?: unknown): void;
|
|
11
|
+
}): Promise<() => void>;
|
|
12
|
+
private request;
|
|
13
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { connectChattingLiveStream } from "./chatting-live-stream";
|
|
2
|
+
import { normalizeBaseURL, toErrorMessage } from "./chatting-utils";
|
|
3
|
+
export class ChattingTransport {
|
|
4
|
+
baseURL;
|
|
5
|
+
fetchImpl;
|
|
6
|
+
constructor(baseURL, fetchImpl) {
|
|
7
|
+
this.baseURL = normalizeBaseURL(baseURL);
|
|
8
|
+
this.fetchImpl = fetchImpl;
|
|
9
|
+
}
|
|
10
|
+
async get(path, query) {
|
|
11
|
+
return this.request(path, { method: "GET", query });
|
|
12
|
+
}
|
|
13
|
+
async post(path, body) {
|
|
14
|
+
return this.request(path, { method: "POST", body });
|
|
15
|
+
}
|
|
16
|
+
async delete(path, body) {
|
|
17
|
+
return this.request(path, { method: "DELETE", body });
|
|
18
|
+
}
|
|
19
|
+
connectLive(path, query, input) {
|
|
20
|
+
return connectChattingLiveStream({
|
|
21
|
+
url: buildURL(this.baseURL, path, query),
|
|
22
|
+
fetchImpl: this.fetchImpl,
|
|
23
|
+
onEvent: input.onEvent,
|
|
24
|
+
onDisconnect: input.onDisconnect
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
async request(path, init) {
|
|
28
|
+
const response = await this.fetchImpl(buildURL(this.baseURL, path, init.query), {
|
|
29
|
+
method: init.method,
|
|
30
|
+
headers: {
|
|
31
|
+
Accept: "application/json",
|
|
32
|
+
...(init.body ? { "Content-Type": "application/json" } : {})
|
|
33
|
+
},
|
|
34
|
+
body: init.body ? JSON.stringify(init.body) : undefined
|
|
35
|
+
});
|
|
36
|
+
const payload = await readPayload(response);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw new Error(payload?.error ?? `Chatting request failed with ${response.status}.`);
|
|
39
|
+
}
|
|
40
|
+
return payload;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function buildURL(baseURL, path, query) {
|
|
44
|
+
const url = new URL(path, `${baseURL}/`);
|
|
45
|
+
for (const [key, value] of Object.entries(query ?? {})) {
|
|
46
|
+
if (value) {
|
|
47
|
+
url.searchParams.set(key, value);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return url.toString();
|
|
51
|
+
}
|
|
52
|
+
async function readPayload(response) {
|
|
53
|
+
const text = await response.text();
|
|
54
|
+
if (!text) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
return JSON.parse(text);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw new Error(toErrorMessage(error));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export type ChattingSender = "user" | "team";
|
|
2
|
+
export interface ChattingSessionState {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
conversationId?: string | null;
|
|
5
|
+
email?: string | null;
|
|
6
|
+
pushToken?: string | null;
|
|
7
|
+
pushPlatform?: string | null;
|
|
8
|
+
pushAppId?: string | null;
|
|
9
|
+
pushTokenSyncedConversationId?: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface ChattingSessionStore {
|
|
12
|
+
load(): Promise<ChattingSessionState | null>;
|
|
13
|
+
save(state: ChattingSessionState): Promise<void>;
|
|
14
|
+
clear?(): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export interface ChattingKeyValueStorage {
|
|
17
|
+
getItem(key: string): Promise<string | null>;
|
|
18
|
+
setItem(key: string, value: string): Promise<void>;
|
|
19
|
+
removeItem?(key: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface ChattingVisitorContext {
|
|
22
|
+
pageUrl?: string | null;
|
|
23
|
+
referrer?: string | null;
|
|
24
|
+
timezone?: string | null;
|
|
25
|
+
locale?: string | null;
|
|
26
|
+
tags?: string[];
|
|
27
|
+
customFields?: Record<string, string>;
|
|
28
|
+
}
|
|
29
|
+
export interface ChattingVisitorProfile {
|
|
30
|
+
email: string;
|
|
31
|
+
name?: string | null;
|
|
32
|
+
phone?: string | null;
|
|
33
|
+
company?: string | null;
|
|
34
|
+
role?: string | null;
|
|
35
|
+
avatarUrl?: string | null;
|
|
36
|
+
status?: string | null;
|
|
37
|
+
tags?: string[];
|
|
38
|
+
customFields?: Record<string, string>;
|
|
39
|
+
}
|
|
40
|
+
export interface ChattingMessageAttachment {
|
|
41
|
+
id: string;
|
|
42
|
+
fileName: string;
|
|
43
|
+
contentType: string;
|
|
44
|
+
sizeBytes: number;
|
|
45
|
+
url: string;
|
|
46
|
+
isImage: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface ChattingMessage {
|
|
49
|
+
id: string;
|
|
50
|
+
content: string;
|
|
51
|
+
createdAt: string;
|
|
52
|
+
sender: ChattingSender;
|
|
53
|
+
attachments: ChattingMessageAttachment[];
|
|
54
|
+
}
|
|
55
|
+
export interface ChattingFAQItem {
|
|
56
|
+
id: string;
|
|
57
|
+
question: string;
|
|
58
|
+
answer: string;
|
|
59
|
+
link?: string | null;
|
|
60
|
+
}
|
|
61
|
+
export interface ChattingFAQSuggestions {
|
|
62
|
+
fallbackMessage: string;
|
|
63
|
+
items: ChattingFAQItem[];
|
|
64
|
+
}
|
|
65
|
+
export interface ChattingConversationState {
|
|
66
|
+
conversationId: string;
|
|
67
|
+
messages: ChattingMessage[];
|
|
68
|
+
faqSuggestions: ChattingFAQSuggestions | null;
|
|
69
|
+
}
|
|
70
|
+
export interface ChattingSendMessageResult {
|
|
71
|
+
conversationId: string;
|
|
72
|
+
message: ChattingMessage;
|
|
73
|
+
faqSuggestions: ChattingFAQSuggestions | null;
|
|
74
|
+
}
|
|
75
|
+
export type ChattingLiveEventType = "connected" | "message.created" | "typing.updated" | "conversation.updated";
|
|
76
|
+
export type ChattingTypingActor = "team" | "visitor";
|
|
77
|
+
export interface ChattingLiveEvent {
|
|
78
|
+
type: ChattingLiveEventType;
|
|
79
|
+
conversationId?: string | null;
|
|
80
|
+
sender?: ChattingSender;
|
|
81
|
+
actor?: ChattingTypingActor;
|
|
82
|
+
typing?: boolean;
|
|
83
|
+
status?: string | null;
|
|
84
|
+
createdAt?: string | null;
|
|
85
|
+
updatedAt?: string | null;
|
|
86
|
+
}
|
|
87
|
+
export interface ChattingSiteConfig {
|
|
88
|
+
id: string;
|
|
89
|
+
widgetTitle: string;
|
|
90
|
+
greetingText?: string | null;
|
|
91
|
+
brandColor?: string | null;
|
|
92
|
+
showOnlineStatus?: boolean | null;
|
|
93
|
+
}
|
|
94
|
+
export interface ChattingSiteStatus {
|
|
95
|
+
online: boolean;
|
|
96
|
+
lastSeenAt?: string | null;
|
|
97
|
+
}
|
|
98
|
+
export interface ChattingClientOptions {
|
|
99
|
+
siteId: string;
|
|
100
|
+
baseURL?: string;
|
|
101
|
+
sessionStore?: ChattingSessionStore;
|
|
102
|
+
fetchImpl?: typeof fetch;
|
|
103
|
+
}
|
|
104
|
+
export interface ChattingPushRegistrationInput {
|
|
105
|
+
pushToken: string;
|
|
106
|
+
platform?: string | null;
|
|
107
|
+
appId?: string | null;
|
|
108
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChattingVisitorContext } from "./chatting-types";
|
|
2
|
+
export declare function createSessionId(): string;
|
|
3
|
+
export declare function normalizeBaseURL(baseURL: string): string;
|
|
4
|
+
export declare function normalizeText(value: string | null | undefined): string | null;
|
|
5
|
+
export declare function resolveContext(context?: ChattingVisitorContext): {
|
|
6
|
+
pageUrl: string | null;
|
|
7
|
+
referrer: string | null;
|
|
8
|
+
timezone: string | null;
|
|
9
|
+
locale: string | null;
|
|
10
|
+
tags: string[];
|
|
11
|
+
customFields: Record<string, string>;
|
|
12
|
+
};
|
|
13
|
+
export declare function toErrorMessage(error: unknown): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export function createSessionId() {
|
|
2
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
3
|
+
return globalThis.crypto.randomUUID().toLowerCase();
|
|
4
|
+
}
|
|
5
|
+
return `chat_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
6
|
+
}
|
|
7
|
+
export function normalizeBaseURL(baseURL) {
|
|
8
|
+
return baseURL.replace(/\/+$/, "");
|
|
9
|
+
}
|
|
10
|
+
export function normalizeText(value) {
|
|
11
|
+
const trimmed = value?.trim();
|
|
12
|
+
return trimmed ? trimmed : null;
|
|
13
|
+
}
|
|
14
|
+
export function resolveContext(context = {}) {
|
|
15
|
+
return {
|
|
16
|
+
pageUrl: normalizeText(context.pageUrl),
|
|
17
|
+
referrer: normalizeText(context.referrer),
|
|
18
|
+
timezone: normalizeText(context.timezone) ?? currentTimeZone(),
|
|
19
|
+
locale: normalizeText(context.locale) ?? currentLocale(),
|
|
20
|
+
tags: context.tags ?? [],
|
|
21
|
+
customFields: context.customFields ?? {}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function toErrorMessage(error) {
|
|
25
|
+
return error instanceof Error ? error.message : "Unknown Chatting error.";
|
|
26
|
+
}
|
|
27
|
+
function currentLocale() {
|
|
28
|
+
return typeof Intl === "object" ? Intl.DateTimeFormat().resolvedOptions().locale : null;
|
|
29
|
+
}
|
|
30
|
+
function currentTimeZone() {
|
|
31
|
+
return typeof Intl === "object" ? Intl.DateTimeFormat().resolvedOptions().timeZone : null;
|
|
32
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ChattingClient } from "./chatting-client";
|
|
2
|
+
export { ChattingConversationScreen } from "./chatting-conversation-screen";
|
|
3
|
+
export { ChattingLiveStreamUnsupportedError } from "./chatting-live-stream";
|
|
4
|
+
export { startConversationPolling } from "./chatting-poller";
|
|
5
|
+
export { createKeyValueSessionStore, createMemorySessionStore } from "./chatting-session-store";
|
|
6
|
+
export { useChattingConversation } from "./use-chatting-conversation";
|
|
7
|
+
export type { ChattingClientOptions, ChattingConversationState, ChattingFAQSuggestions, ChattingKeyValueStorage, ChattingLiveEvent, ChattingLiveEventType, ChattingMessage, ChattingPushRegistrationInput, ChattingSessionState, ChattingSessionStore, ChattingSiteConfig, ChattingSiteStatus, ChattingTypingActor, ChattingVisitorContext, ChattingVisitorProfile } from "./chatting-types";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ChattingClient } from "./chatting-client";
|
|
2
|
+
export { ChattingConversationScreen } from "./chatting-conversation-screen";
|
|
3
|
+
export { ChattingLiveStreamUnsupportedError } from "./chatting-live-stream";
|
|
4
|
+
export { startConversationPolling } from "./chatting-poller";
|
|
5
|
+
export { createKeyValueSessionStore, createMemorySessionStore } from "./chatting-session-store";
|
|
6
|
+
export { useChattingConversation } from "./use-chatting-conversation";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ChattingClient } from "./chatting-client";
|
|
2
|
+
import type { ChattingFAQSuggestions, ChattingMessage, ChattingSiteConfig, ChattingSiteStatus, ChattingVisitorContext, ChattingVisitorProfile } from "./chatting-types";
|
|
3
|
+
export declare function useChattingConversation(input: {
|
|
4
|
+
client: ChattingClient;
|
|
5
|
+
context?: ChattingVisitorContext;
|
|
6
|
+
profile?: ChattingVisitorProfile | null;
|
|
7
|
+
draftVisitorEmail?: string | null;
|
|
8
|
+
pollIntervalMs?: number;
|
|
9
|
+
}): {
|
|
10
|
+
siteConfig: ChattingSiteConfig | null;
|
|
11
|
+
siteStatus: ChattingSiteStatus | null;
|
|
12
|
+
messages: ChattingMessage[];
|
|
13
|
+
faqSuggestions: ChattingFAQSuggestions | null;
|
|
14
|
+
draftMessage: string;
|
|
15
|
+
emailAddress: string;
|
|
16
|
+
teamTyping: boolean;
|
|
17
|
+
errorMessage: string | null;
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
isSending: boolean;
|
|
20
|
+
isSavingEmail: boolean;
|
|
21
|
+
setDraftMessage: (value: string) => void;
|
|
22
|
+
setEmailAddress: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
23
|
+
refreshConversation: () => Promise<void>;
|
|
24
|
+
sendMessage: () => Promise<void>;
|
|
25
|
+
saveEmail: () => Promise<void>;
|
|
26
|
+
};
|