@usechatting/react-native 0.1.0 → 0.1.2

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 CHANGED
@@ -1,14 +1,6 @@
1
1
  # @usechatting/react-native
2
2
 
3
- Expo-friendly React Native chat package for Chatting.
4
-
5
- ## What it includes
6
-
7
- - JavaScript client for Chatting public chat APIs
8
- - pluggable async session storage
9
- - React hook for conversation state
10
- - simple React Native chat screen
11
- - live conversation sync with automatic polling fallback
3
+ Add Chatting customer support to an Expo or React Native app.
12
4
 
13
5
  ## Install
14
6
 
@@ -16,107 +8,46 @@ Expo-friendly React Native chat package for Chatting.
16
8
  npm install @usechatting/react-native
17
9
  ```
18
10
 
19
- If you want session persistence across app restarts, also install an async storage adapter in your app, for example React Native Async Storage.
20
-
21
- For Expo push notifications in your host app, also install:
22
-
23
- ```bash
24
- npx expo install expo-notifications
25
- ```
26
-
27
- ## Required config
11
+ ## Get your site ID
28
12
 
29
- - `baseURL`: use `https://usechatting.com`
30
- - `siteId`: your site/workspace ID inside Chatting
13
+ Open [Widget Installation](https://usechatting.com/dashboard/widget?tab=installation) in Chatting and copy the `data-site-id` value.
31
14
 
32
- ## Exact Expo integration snippet
15
+ ## Add the support screen
33
16
 
34
17
  ```tsx
35
- import { useEffect, useMemo, useState } from "react";
36
- import AsyncStorage from "@react-native-async-storage/async-storage";
37
- import * as Notifications from "expo-notifications";
38
- import { AppState, Platform } from "react-native";
39
18
  import {
40
19
  ChattingClient,
41
- ChattingConversationScreen,
42
- createKeyValueSessionStore
20
+ ChattingConversationScreen
43
21
  } from "@usechatting/react-native";
44
22
 
45
- Notifications.setNotificationHandler({
46
- handleNotification: async () => ({
47
- shouldShowAlert: false,
48
- shouldPlaySound: false,
49
- shouldSetBadge: false
50
- })
51
- });
52
-
53
23
  const client = new ChattingClient({
54
- baseURL: "https://usechatting.com",
55
- siteId: "your-site-id",
56
- sessionStore: createKeyValueSessionStore(AsyncStorage, "your-site-id")
24
+ siteId: "your-site-id"
57
25
  });
58
26
 
59
27
  export function SupportScreen() {
60
- const [refreshKey, setRefreshKey] = useState(0);
61
- const context = useMemo(() => ({ pageUrl: "myapp://support" }), []);
62
-
63
- useEffect(() => {
64
- let mounted = true;
65
- const refreshChat = async () => {
66
- await client.syncPushToken();
67
- if (mounted) {
68
- setRefreshKey((current) => current + 1);
69
- }
70
- };
71
-
72
- const registerPush = async () => {
73
- const permission = await Notifications.requestPermissionsAsync();
74
- if (!mounted || permission.status !== "granted") {
75
- return;
76
- }
77
-
78
- const token = await Notifications.getExpoPushTokenAsync({
79
- projectId: "your-expo-project-id"
80
- });
81
-
82
- await client.registerPushToken({
83
- pushToken: token.data,
84
- platform: Platform.OS
85
- });
86
- };
87
-
88
- void registerPush();
89
-
90
- const appStateSubscription = AppState.addEventListener("change", (nextState) => {
91
- if (nextState === "active") {
92
- void refreshChat();
93
- }
94
- });
95
-
96
- const responseSubscription = Notifications.addNotificationResponseReceivedListener(() => {
97
- void refreshChat();
98
- });
99
-
100
- return () => {
101
- mounted = false;
102
- appStateSubscription.remove();
103
- responseSubscription.remove();
104
- };
105
- }, []);
106
-
107
- return (
108
- <ChattingConversationScreen
109
- key={refreshKey}
110
- client={client}
111
- context={context}
112
- draftVisitorEmail="customer@example.com"
113
- />
114
- );
28
+ return <ChattingConversationScreen client={client} />;
115
29
  }
116
30
  ```
117
31
 
118
- ## Realtime behavior
32
+ Messages sent here appear in your Chatting inbox. Team replies appear in the app while the screen is open.
33
+
34
+ ## Keep conversations after the app closes
35
+
36
+ Add `persistSession: true` so customers can reopen the same conversation later:
37
+
38
+ ```tsx
39
+ import { ChattingClient } from "@usechatting/react-native";
40
+
41
+ const client = new ChattingClient({
42
+ siteId: "your-site-id",
43
+ persistSession: true
44
+ });
45
+ ```
46
+
47
+ ## Optional features
119
48
 
120
- This package uses a dedicated React Native live transport for Chatting's SSE conversation stream, so new team messages and team typing updates show up immediately while the app is open. If that live connection drops, the hook falls back to foreground polling so the conversation stays usable while reconnecting.
49
+ - Pass a signed-in customer to the screen with `profile={signedInCustomer}`.
50
+ - Register an Expo push token if customers should receive phone notifications when your team replies and the app is not open.
51
+ - Use `useChattingConversation` instead of the ready-made screen if you want to build your own interface.
121
52
 
122
- Expo push delivery is now supported for background and suspended apps once the host app registers an Expo push token through `client.registerPushToken(...)`. When the app becomes active again or a notification is tapped, call `client.syncPushToken()` and remount or refresh your chat screen so the conversation refetches cleanly.
53
+ See the [complete setup guide](https://usechatting.com/guides/chatting-react-native-expo-guide).
@@ -1,4 +1,4 @@
1
- import type { ChattingClientOptions, ChattingConversationState, ChattingLiveEvent, ChattingPushRegistrationInput, ChattingSendMessageResult, ChattingSessionState, ChattingSiteConfig, ChattingSiteStatus, ChattingVisitorContext, ChattingVisitorProfile } from "./chatting-types";
1
+ import type { ChattingClientOptions, ChattingConversationState, ChattingLiveEvent, ChattingPushRegistrationInput, ChattingSendMessageResult, ChattingSessionState, ChattingSiteStatus, ChattingVisitorContext, ChattingVisitorProfile } from "./chatting-types";
2
2
  export declare class ChattingClient {
3
3
  readonly siteId: string;
4
4
  private readonly sessionStore;
@@ -7,7 +7,7 @@ export declare class ChattingClient {
7
7
  currentSessionState(): Promise<ChattingSessionState>;
8
8
  clearConversation(): Promise<void>;
9
9
  saveEmail(email: string): Promise<void>;
10
- fetchSiteConfig(context?: ChattingVisitorContext): Promise<ChattingSiteConfig>;
10
+ fetchSiteConfig(context?: ChattingVisitorContext): Promise<import("./chatting-types").ChattingSiteConfig>;
11
11
  fetchSiteStatus(context?: ChattingVisitorContext): Promise<ChattingSiteStatus>;
12
12
  fetchConversationIfAvailable(): Promise<ChattingConversationState | null>;
13
13
  fetchConversation(): Promise<ChattingConversationState>;
@@ -1,4 +1,5 @@
1
- import { createMemorySessionStore } from "./chatting-session-store";
1
+ import { resolveChattingSessionStore } from "./chatting-session-store";
2
+ import { fetchChattingSiteConfig } from "./chatting-sdk-presence";
2
3
  import { buildChattingSiteQuery, DEFAULT_CHATTING_BASE_URL, requireChattingText } from "./chatting-client-shared";
3
4
  import { clearConversationPushState, registerChattingPushToken, syncChattingPushToken, unregisterChattingPushToken } from "./chatting-push-registration";
4
5
  import { ChattingTransport } from "./chatting-transport";
@@ -9,7 +10,7 @@ export class ChattingClient {
9
10
  transport;
10
11
  constructor(options) {
11
12
  this.siteId = options.siteId;
12
- this.sessionStore = options.sessionStore ?? createMemorySessionStore();
13
+ this.sessionStore = resolveChattingSessionStore(options);
13
14
  this.transport = new ChattingTransport(options.baseURL ?? DEFAULT_CHATTING_BASE_URL, options.fetchImpl ?? fetch);
14
15
  }
15
16
  async currentSessionState() {
@@ -42,11 +43,12 @@ export class ChattingClient {
42
43
  }
43
44
  async fetchSiteConfig(context = {}) {
44
45
  const state = await this.currentSessionState();
45
- const response = await this.transport.get("/api/public/site-config", {
46
- ...buildChattingSiteQuery(this.siteId, state, resolveContext(context)),
47
- conversationId: state.conversationId ?? null
46
+ return fetchChattingSiteConfig({
47
+ transport: this.transport,
48
+ siteId: this.siteId,
49
+ state,
50
+ context: resolveContext(context)
48
51
  });
49
- return response.site;
50
52
  }
51
53
  async fetchSiteStatus(context = {}) {
52
54
  const state = await this.currentSessionState();
@@ -5,12 +5,13 @@ import { styles } from "./chatting-screen-styles";
5
5
  export function ChattingConversationScreen(input) {
6
6
  const conversation = useChattingConversation(input);
7
7
  const title = conversation.siteConfig?.widgetTitle ?? "Chatting";
8
- const subtitle = conversation.siteConfig?.showOnlineStatus !== false && conversation.siteStatus
8
+ const greeting = conversation.siteConfig?.greetingText?.trim() || "Start a conversation";
9
+ const teamStatus = conversation.siteConfig?.showOnlineStatus !== false && conversation.siteStatus
9
10
  ? conversation.siteStatus.online
10
11
  ? "Team is online"
11
12
  : "Team is away"
12
- : conversation.siteConfig?.greetingText ?? "Start a conversation";
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: subtitle })] }), _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: "#2563EB" }) : null, !conversation.isLoading && conversation.messages.length === 0 ? (_jsx(View, { style: styles.banner, children: _jsx(Text, { style: styles.bannerText, children: "Open support inside your app without rebuilding visitor chat from scratch." }) })) : 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 }), _jsx(View, { style: styles.spacer })] })) : (_jsxs(_Fragment, { children: [_jsx(View, { style: styles.spacer }), _jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: true })] })) }, message.id))), conversation.teamTyping ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: "Team is typing...", isUser: false, subtle: true }), _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] }), _jsxs(View, { style: styles.footer, children: [_jsx(TextInput, { value: conversation.emailAddress, onChangeText: conversation.setEmailAddress, placeholder: "Email for follow-up", autoCapitalize: "none", autoCorrect: false, style: styles.input }), _jsx(TextInput, { value: conversation.draftMessage, onChangeText: conversation.setDraftMessage, placeholder: "Type a message", multiline: true, style: [styles.input, styles.composer] }), _jsxs(View, { style: styles.actions, children: [_jsx(TouchableOpacity, { style: [styles.button, styles.secondaryButton], onPress: () => void conversation.saveEmail(), children: _jsx(Text, { style: styles.secondaryButtonText, children: conversation.isSavingEmail ? "Saving..." : "Save email" }) }), _jsx(TouchableOpacity, { style: styles.button, onPress: () => void conversation.sendMessage(), children: _jsx(Text, { style: styles.buttonText, children: conversation.isSending ? "Sending..." : "Send" }) })] })] })] }));
13
+ : null;
14
+ return (_jsxs(View, { style: styles.screen, children: [_jsxs(View, { style: styles.header, children: [_jsx(Text, { style: styles.title, children: title }), 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: "#2563EB" }) : null, !conversation.isLoading && conversation.messages.length === 0 ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: greeting, isUser: false }), _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 }), _jsx(View, { style: styles.spacer })] })) : (_jsxs(_Fragment, { children: [_jsx(View, { style: styles.spacer }), _jsx(Bubble, { message: message.content || "(attachment placeholder)", isUser: true })] })) }, message.id))), conversation.teamTyping ? (_jsxs(View, { style: styles.row, children: [_jsx(Bubble, { message: "Team is typing...", isUser: false, subtle: true }), _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], onPress: () => void conversation.sendMessage(), children: _jsx(Text, { style: styles.buttonText, children: conversation.isSending ? "Sending..." : "Send" }) })] }) })] }));
14
15
  }
15
16
  function Bubble(input) {
16
17
  return (_jsx(View, { style: [
@@ -4,9 +4,9 @@ export declare const styles: {
4
4
  backgroundColor: string;
5
5
  };
6
6
  header: {
7
- padding: number;
8
- borderBottomWidth: number;
9
- borderBottomColor: string;
7
+ paddingHorizontal: number;
8
+ paddingTop: number;
9
+ paddingBottom: number;
10
10
  backgroundColor: string;
11
11
  };
12
12
  title: {
@@ -25,6 +25,7 @@ export declare const styles: {
25
25
  content: {
26
26
  padding: number;
27
27
  gap: number;
28
+ flexGrow: number;
28
29
  };
29
30
  banner: {
30
31
  padding: number;
@@ -60,8 +61,15 @@ export declare const styles: {
60
61
  };
61
62
  teamBubble: {
62
63
  backgroundColor: string;
63
- borderWidth: number;
64
- borderColor: string;
64
+ borderBottomLeftRadius: number;
65
+ shadowColor: string;
66
+ shadowOpacity: number;
67
+ shadowRadius: number;
68
+ shadowOffset: {
69
+ width: number;
70
+ height: number;
71
+ };
72
+ elevation: number;
65
73
  };
66
74
  typingBubble: {
67
75
  opacity: number;
@@ -100,12 +108,16 @@ export declare const styles: {
100
108
  color: string;
101
109
  };
102
110
  footer: {
103
- gap: number;
104
111
  padding: number;
105
112
  borderTopWidth: number;
106
113
  borderTopColor: string;
107
114
  backgroundColor: string;
108
115
  };
116
+ composerRow: {
117
+ flexDirection: string;
118
+ alignItems: string;
119
+ gap: number;
120
+ };
109
121
  input: {
110
122
  borderWidth: number;
111
123
  borderColor: string;
@@ -116,14 +128,11 @@ export declare const styles: {
116
128
  color: string;
117
129
  };
118
130
  composer: {
131
+ flex: number;
119
132
  minHeight: number;
120
133
  maxHeight: number;
121
134
  textAlignVertical: string;
122
135
  };
123
- actions: {
124
- flexDirection: string;
125
- gap: number;
126
- };
127
136
  button: {
128
137
  flex: number;
129
138
  borderRadius: number;
@@ -132,15 +141,13 @@ export declare const styles: {
132
141
  justifyContent: string;
133
142
  backgroundColor: string;
134
143
  };
135
- secondaryButton: {
136
- backgroundColor: string;
144
+ sendButton: {
145
+ flex: number;
146
+ minHeight: number;
147
+ paddingHorizontal: number;
137
148
  };
138
149
  buttonText: {
139
150
  color: string;
140
151
  fontWeight: string;
141
152
  };
142
- secondaryButtonText: {
143
- color: string;
144
- fontWeight: string;
145
- };
146
153
  };
@@ -1,11 +1,11 @@
1
1
  import { StyleSheet } from "react-native";
2
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" },
3
+ screen: { flex: 1, backgroundColor: "#F6F8FB" },
4
+ header: { paddingHorizontal: 18, paddingTop: 18, paddingBottom: 16, backgroundColor: "#2563EB" },
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" },
@@ -13,7 +13,15 @@ export const styles = StyleSheet.create({
13
13
  spacer: { flex: 1, minWidth: 40 },
14
14
  bubble: { maxWidth: "78%", borderRadius: 18, paddingHorizontal: 14, paddingVertical: 10 },
15
15
  userBubble: { backgroundColor: "#2563EB" },
16
- teamBubble: { backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0" },
16
+ teamBubble: {
17
+ backgroundColor: "#FFFFFF",
18
+ borderBottomLeftRadius: 6,
19
+ shadowColor: "#0F172A",
20
+ shadowOpacity: 0.08,
21
+ shadowRadius: 10,
22
+ shadowOffset: { width: 0, height: 4 },
23
+ elevation: 2
24
+ },
17
25
  typingBubble: { opacity: 0.8 },
18
26
  userText: { color: "#FFFFFF", fontSize: 15, lineHeight: 22 },
19
27
  teamText: { color: "#0F172A", fontSize: 15, lineHeight: 22 },
@@ -21,12 +29,11 @@ export const styles = StyleSheet.create({
21
29
  faqCard: { padding: 12, borderRadius: 14, backgroundColor: "#FFFFFF", borderWidth: 1, borderColor: "#E2E8F0", gap: 4 },
22
30
  faqTitle: { fontSize: 14, fontWeight: "700", color: "#0F172A" },
23
31
  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
+ footer: { padding: 14, borderTopWidth: 1, borderTopColor: "#E2E8F0", backgroundColor: "#FFFFFF" },
33
+ composerRow: { flexDirection: "row", alignItems: "flex-end", gap: 8 },
34
+ input: { borderWidth: 1, borderColor: "#CBD5E1", borderRadius: 20, paddingHorizontal: 14, paddingVertical: 10, backgroundColor: "#F8FAFC", color: "#0F172A" },
35
+ composer: { flex: 1, minHeight: 44, maxHeight: 120, textAlignVertical: "top" },
36
+ button: { flex: 1, borderRadius: 20, paddingVertical: 12, alignItems: "center", justifyContent: "center", backgroundColor: "#2563EB" },
37
+ sendButton: { flex: 0, minHeight: 44, paddingHorizontal: 18 },
38
+ buttonText: { color: "#FFFFFF", fontWeight: "700" }
32
39
  });
@@ -0,0 +1,9 @@
1
+ import { ChattingTransport } from "./chatting-transport";
2
+ import type { ChattingSessionState, ChattingSiteConfig } from "./chatting-types";
3
+ import type { resolveContext } from "./chatting-utils";
4
+ export declare function fetchChattingSiteConfig(input: {
5
+ transport: ChattingTransport;
6
+ siteId: string;
7
+ state: ChattingSessionState;
8
+ context: ReturnType<typeof resolveContext>;
9
+ }): Promise<ChattingSiteConfig>;
@@ -0,0 +1,10 @@
1
+ import { buildChattingSiteQuery } from "./chatting-client-shared";
2
+ export async function fetchChattingSiteConfig(input) {
3
+ const request = buildChattingSiteQuery(input.siteId, input.state, input.context);
4
+ await input.transport.post("/api/public/sdk-presence", request).catch(() => undefined);
5
+ const response = await input.transport.get("/api/public/site-config", {
6
+ ...request,
7
+ conversationId: input.state.conversationId ?? null
8
+ });
9
+ return response.site;
10
+ }
@@ -1,3 +1,4 @@
1
- import type { ChattingKeyValueStorage, ChattingSessionStore } from "./chatting-types";
1
+ import type { ChattingClientOptions, ChattingKeyValueStorage, ChattingSessionStore } from "./chatting-types";
2
+ export declare function resolveChattingSessionStore(options: ChattingClientOptions): ChattingSessionStore;
2
3
  export declare function createMemorySessionStore(): ChattingSessionStore;
3
4
  export declare function createKeyValueSessionStore(storage: ChattingKeyValueStorage, namespace: string): ChattingSessionStore;
@@ -1,3 +1,12 @@
1
+ import AsyncStorage from "@react-native-async-storage/async-storage";
2
+ export function resolveChattingSessionStore(options) {
3
+ if (options.sessionStore) {
4
+ return options.sessionStore;
5
+ }
6
+ return options.persistSession
7
+ ? createKeyValueSessionStore(AsyncStorage, options.siteId)
8
+ : createMemorySessionStore();
9
+ }
1
10
  export function createMemorySessionStore() {
2
11
  let state = null;
3
12
  return {
@@ -98,6 +98,7 @@ export interface ChattingSiteStatus {
98
98
  export interface ChattingClientOptions {
99
99
  siteId: string;
100
100
  baseURL?: string;
101
+ persistSession?: boolean;
101
102
  sessionStore?: ChattingSessionStore;
102
103
  fetchImpl?: typeof fetch;
103
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usechatting/react-native",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "React Native and Expo visitor chat SDK for Chatting.",
5
5
  "license": "Proprietary",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,9 @@
14
14
  "scripts": {
15
15
  "build": "tsc -p tsconfig.json"
16
16
  },
17
+ "dependencies": {
18
+ "@react-native-async-storage/async-storage": "2.2.0"
19
+ },
17
20
  "peerDependencies": {
18
21
  "react": ">=18",
19
22
  "react-native": ">=0.74"