@parlr/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.
Files changed (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +918 -0
  3. package/lib/commonjs/components/AttachmentPicker.js +292 -0
  4. package/lib/commonjs/components/AttachmentPicker.js.map +1 -0
  5. package/lib/commonjs/components/AttachmentPreview.js +200 -0
  6. package/lib/commonjs/components/AttachmentPreview.js.map +1 -0
  7. package/lib/commonjs/components/ChatBubble.js +391 -0
  8. package/lib/commonjs/components/ChatBubble.js.map +1 -0
  9. package/lib/commonjs/components/EmptyState.js +115 -0
  10. package/lib/commonjs/components/EmptyState.js.map +1 -0
  11. package/lib/commonjs/components/ParlrChat.js +745 -0
  12. package/lib/commonjs/components/ParlrChat.js.map +1 -0
  13. package/lib/commonjs/components/ParlrConversationList.js +509 -0
  14. package/lib/commonjs/components/ParlrConversationList.js.map +1 -0
  15. package/lib/commonjs/components/PreChatForm.js +263 -0
  16. package/lib/commonjs/components/PreChatForm.js.map +1 -0
  17. package/lib/commonjs/components/RichMessage.js +284 -0
  18. package/lib/commonjs/components/RichMessage.js.map +1 -0
  19. package/lib/commonjs/components/SatisfactionSurvey.js +292 -0
  20. package/lib/commonjs/components/SatisfactionSurvey.js.map +1 -0
  21. package/lib/commonjs/components/TypingIndicator.js +86 -0
  22. package/lib/commonjs/components/TypingIndicator.js.map +1 -0
  23. package/lib/commonjs/core/api.js +310 -0
  24. package/lib/commonjs/core/api.js.map +1 -0
  25. package/lib/commonjs/core/config.js +40 -0
  26. package/lib/commonjs/core/config.js.map +1 -0
  27. package/lib/commonjs/core/errors.js +73 -0
  28. package/lib/commonjs/core/errors.js.map +1 -0
  29. package/lib/commonjs/core/offlineQueue.js +89 -0
  30. package/lib/commonjs/core/offlineQueue.js.map +1 -0
  31. package/lib/commonjs/core/pushNotifications.js +21 -0
  32. package/lib/commonjs/core/pushNotifications.js.map +1 -0
  33. package/lib/commonjs/core/session.js +130 -0
  34. package/lib/commonjs/core/session.js.map +1 -0
  35. package/lib/commonjs/core/theme.js +110 -0
  36. package/lib/commonjs/core/theme.js.map +1 -0
  37. package/lib/commonjs/core/types.js +6 -0
  38. package/lib/commonjs/core/types.js.map +1 -0
  39. package/lib/commonjs/core/websocket.js +245 -0
  40. package/lib/commonjs/core/websocket.js.map +1 -0
  41. package/lib/commonjs/hooks/useChat.js +462 -0
  42. package/lib/commonjs/hooks/useChat.js.map +1 -0
  43. package/lib/commonjs/hooks/useParlr.js +44 -0
  44. package/lib/commonjs/hooks/useParlr.js.map +1 -0
  45. package/lib/commonjs/index.js +185 -0
  46. package/lib/commonjs/index.js.map +1 -0
  47. package/lib/commonjs/package.json +1 -0
  48. package/lib/commonjs/provider/ParlrContext.js +38 -0
  49. package/lib/commonjs/provider/ParlrContext.js.map +1 -0
  50. package/lib/commonjs/provider/ParlrProvider.js +256 -0
  51. package/lib/commonjs/provider/ParlrProvider.js.map +1 -0
  52. package/lib/module/components/AttachmentPicker.js +287 -0
  53. package/lib/module/components/AttachmentPicker.js.map +1 -0
  54. package/lib/module/components/AttachmentPreview.js +195 -0
  55. package/lib/module/components/AttachmentPreview.js.map +1 -0
  56. package/lib/module/components/ChatBubble.js +386 -0
  57. package/lib/module/components/ChatBubble.js.map +1 -0
  58. package/lib/module/components/EmptyState.js +110 -0
  59. package/lib/module/components/EmptyState.js.map +1 -0
  60. package/lib/module/components/ParlrChat.js +740 -0
  61. package/lib/module/components/ParlrChat.js.map +1 -0
  62. package/lib/module/components/ParlrConversationList.js +504 -0
  63. package/lib/module/components/ParlrConversationList.js.map +1 -0
  64. package/lib/module/components/PreChatForm.js +258 -0
  65. package/lib/module/components/PreChatForm.js.map +1 -0
  66. package/lib/module/components/RichMessage.js +280 -0
  67. package/lib/module/components/RichMessage.js.map +1 -0
  68. package/lib/module/components/SatisfactionSurvey.js +287 -0
  69. package/lib/module/components/SatisfactionSurvey.js.map +1 -0
  70. package/lib/module/components/TypingIndicator.js +81 -0
  71. package/lib/module/components/TypingIndicator.js.map +1 -0
  72. package/lib/module/core/api.js +305 -0
  73. package/lib/module/core/api.js.map +1 -0
  74. package/lib/module/core/config.js +36 -0
  75. package/lib/module/core/config.js.map +1 -0
  76. package/lib/module/core/errors.js +64 -0
  77. package/lib/module/core/errors.js.map +1 -0
  78. package/lib/module/core/offlineQueue.js +82 -0
  79. package/lib/module/core/offlineQueue.js.map +1 -0
  80. package/lib/module/core/pushNotifications.js +16 -0
  81. package/lib/module/core/pushNotifications.js.map +1 -0
  82. package/lib/module/core/session.js +122 -0
  83. package/lib/module/core/session.js.map +1 -0
  84. package/lib/module/core/theme.js +105 -0
  85. package/lib/module/core/theme.js.map +1 -0
  86. package/lib/module/core/types.js +4 -0
  87. package/lib/module/core/types.js.map +1 -0
  88. package/lib/module/core/websocket.js +241 -0
  89. package/lib/module/core/websocket.js.map +1 -0
  90. package/lib/module/hooks/useChat.js +458 -0
  91. package/lib/module/hooks/useChat.js.map +1 -0
  92. package/lib/module/hooks/useParlr.js +40 -0
  93. package/lib/module/hooks/useParlr.js.map +1 -0
  94. package/lib/module/index.js +58 -0
  95. package/lib/module/index.js.map +1 -0
  96. package/lib/module/package.json +1 -0
  97. package/lib/module/provider/ParlrContext.js +35 -0
  98. package/lib/module/provider/ParlrContext.js.map +1 -0
  99. package/lib/module/provider/ParlrProvider.js +251 -0
  100. package/lib/module/provider/ParlrProvider.js.map +1 -0
  101. package/lib/typescript/commonjs/components/AttachmentPicker.d.ts +23 -0
  102. package/lib/typescript/commonjs/components/AttachmentPicker.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/components/AttachmentPreview.d.ts +16 -0
  104. package/lib/typescript/commonjs/components/AttachmentPreview.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/components/ChatBubble.d.ts +14 -0
  106. package/lib/typescript/commonjs/components/ChatBubble.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/components/EmptyState.d.ts +10 -0
  108. package/lib/typescript/commonjs/components/EmptyState.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/components/ParlrChat.d.ts +34 -0
  110. package/lib/typescript/commonjs/components/ParlrChat.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/components/ParlrConversationList.d.ts +17 -0
  112. package/lib/typescript/commonjs/components/ParlrConversationList.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/components/PreChatForm.d.ts +20 -0
  114. package/lib/typescript/commonjs/components/PreChatForm.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/components/RichMessage.d.ts +41 -0
  116. package/lib/typescript/commonjs/components/RichMessage.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/components/SatisfactionSurvey.d.ts +17 -0
  118. package/lib/typescript/commonjs/components/SatisfactionSurvey.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/components/TypingIndicator.d.ts +7 -0
  120. package/lib/typescript/commonjs/components/TypingIndicator.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/core/api.d.ts +37 -0
  122. package/lib/typescript/commonjs/core/api.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/core/config.d.ts +9 -0
  124. package/lib/typescript/commonjs/core/config.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/core/errors.d.ts +35 -0
  126. package/lib/typescript/commonjs/core/errors.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/core/offlineQueue.d.ts +16 -0
  128. package/lib/typescript/commonjs/core/offlineQueue.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/core/pushNotifications.d.ts +6 -0
  130. package/lib/typescript/commonjs/core/pushNotifications.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/core/session.d.ts +15 -0
  132. package/lib/typescript/commonjs/core/session.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/core/theme.d.ts +43 -0
  134. package/lib/typescript/commonjs/core/theme.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/core/types.d.ts +185 -0
  136. package/lib/typescript/commonjs/core/types.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/core/websocket.d.ts +17 -0
  138. package/lib/typescript/commonjs/core/websocket.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/hooks/useChat.d.ts +35 -0
  140. package/lib/typescript/commonjs/hooks/useChat.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/hooks/useParlr.d.ts +11 -0
  142. package/lib/typescript/commonjs/hooks/useParlr.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/index.d.ts +30 -0
  144. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/package.json +1 -0
  146. package/lib/typescript/commonjs/provider/ParlrContext.d.ts +13 -0
  147. package/lib/typescript/commonjs/provider/ParlrContext.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/provider/ParlrProvider.d.ts +5 -0
  149. package/lib/typescript/commonjs/provider/ParlrProvider.d.ts.map +1 -0
  150. package/lib/typescript/module/components/AttachmentPicker.d.ts +23 -0
  151. package/lib/typescript/module/components/AttachmentPicker.d.ts.map +1 -0
  152. package/lib/typescript/module/components/AttachmentPreview.d.ts +16 -0
  153. package/lib/typescript/module/components/AttachmentPreview.d.ts.map +1 -0
  154. package/lib/typescript/module/components/ChatBubble.d.ts +14 -0
  155. package/lib/typescript/module/components/ChatBubble.d.ts.map +1 -0
  156. package/lib/typescript/module/components/EmptyState.d.ts +10 -0
  157. package/lib/typescript/module/components/EmptyState.d.ts.map +1 -0
  158. package/lib/typescript/module/components/ParlrChat.d.ts +34 -0
  159. package/lib/typescript/module/components/ParlrChat.d.ts.map +1 -0
  160. package/lib/typescript/module/components/ParlrConversationList.d.ts +17 -0
  161. package/lib/typescript/module/components/ParlrConversationList.d.ts.map +1 -0
  162. package/lib/typescript/module/components/PreChatForm.d.ts +20 -0
  163. package/lib/typescript/module/components/PreChatForm.d.ts.map +1 -0
  164. package/lib/typescript/module/components/RichMessage.d.ts +41 -0
  165. package/lib/typescript/module/components/RichMessage.d.ts.map +1 -0
  166. package/lib/typescript/module/components/SatisfactionSurvey.d.ts +17 -0
  167. package/lib/typescript/module/components/SatisfactionSurvey.d.ts.map +1 -0
  168. package/lib/typescript/module/components/TypingIndicator.d.ts +7 -0
  169. package/lib/typescript/module/components/TypingIndicator.d.ts.map +1 -0
  170. package/lib/typescript/module/core/api.d.ts +37 -0
  171. package/lib/typescript/module/core/api.d.ts.map +1 -0
  172. package/lib/typescript/module/core/config.d.ts +9 -0
  173. package/lib/typescript/module/core/config.d.ts.map +1 -0
  174. package/lib/typescript/module/core/errors.d.ts +35 -0
  175. package/lib/typescript/module/core/errors.d.ts.map +1 -0
  176. package/lib/typescript/module/core/offlineQueue.d.ts +16 -0
  177. package/lib/typescript/module/core/offlineQueue.d.ts.map +1 -0
  178. package/lib/typescript/module/core/pushNotifications.d.ts +6 -0
  179. package/lib/typescript/module/core/pushNotifications.d.ts.map +1 -0
  180. package/lib/typescript/module/core/session.d.ts +15 -0
  181. package/lib/typescript/module/core/session.d.ts.map +1 -0
  182. package/lib/typescript/module/core/theme.d.ts +43 -0
  183. package/lib/typescript/module/core/theme.d.ts.map +1 -0
  184. package/lib/typescript/module/core/types.d.ts +185 -0
  185. package/lib/typescript/module/core/types.d.ts.map +1 -0
  186. package/lib/typescript/module/core/websocket.d.ts +17 -0
  187. package/lib/typescript/module/core/websocket.d.ts.map +1 -0
  188. package/lib/typescript/module/hooks/useChat.d.ts +35 -0
  189. package/lib/typescript/module/hooks/useChat.d.ts.map +1 -0
  190. package/lib/typescript/module/hooks/useParlr.d.ts +11 -0
  191. package/lib/typescript/module/hooks/useParlr.d.ts.map +1 -0
  192. package/lib/typescript/module/index.d.ts +30 -0
  193. package/lib/typescript/module/index.d.ts.map +1 -0
  194. package/lib/typescript/module/package.json +1 -0
  195. package/lib/typescript/module/provider/ParlrContext.d.ts +13 -0
  196. package/lib/typescript/module/provider/ParlrContext.d.ts.map +1 -0
  197. package/lib/typescript/module/provider/ParlrProvider.d.ts +5 -0
  198. package/lib/typescript/module/provider/ParlrProvider.d.ts.map +1 -0
  199. package/package.json +120 -0
  200. package/src/components/AttachmentPicker.tsx +310 -0
  201. package/src/components/AttachmentPreview.tsx +209 -0
  202. package/src/components/ChatBubble.tsx +424 -0
  203. package/src/components/EmptyState.tsx +118 -0
  204. package/src/components/ParlrChat.tsx +863 -0
  205. package/src/components/ParlrConversationList.tsx +559 -0
  206. package/src/components/PreChatForm.tsx +313 -0
  207. package/src/components/RichMessage.tsx +353 -0
  208. package/src/components/SatisfactionSurvey.tsx +333 -0
  209. package/src/components/TypingIndicator.tsx +89 -0
  210. package/src/core/api.ts +406 -0
  211. package/src/core/config.ts +39 -0
  212. package/src/core/errors.ts +68 -0
  213. package/src/core/offlineQueue.ts +94 -0
  214. package/src/core/pushNotifications.ts +22 -0
  215. package/src/core/session.ts +156 -0
  216. package/src/core/theme.ts +133 -0
  217. package/src/core/types.ts +237 -0
  218. package/src/core/websocket.ts +270 -0
  219. package/src/hooks/useChat.ts +534 -0
  220. package/src/hooks/useParlr.ts +43 -0
  221. package/src/index.ts +98 -0
  222. package/src/provider/ParlrContext.ts +40 -0
  223. package/src/provider/ParlrProvider.tsx +338 -0
@@ -0,0 +1,156 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Parlr React Native SDK - Session Manager
3
+ // ---------------------------------------------------------------------------
4
+ //
5
+ // Manages the widget session lifecycle. Uses expo-secure-store when available,
6
+ // falls back to in-memory storage otherwise.
7
+ // ---------------------------------------------------------------------------
8
+
9
+ import type { Session } from './types';
10
+
11
+ const STORE_KEY_PREFIX = 'parlr_session_';
12
+
13
+ function storeKey(workspaceId: string): string {
14
+ return `${STORE_KEY_PREFIX}${workspaceId}`;
15
+ }
16
+
17
+ // ---------------------------------------------------------------------------
18
+ // Storage abstraction with fallback
19
+ // ---------------------------------------------------------------------------
20
+
21
+ interface StorageAdapter {
22
+ getItem(key: string): Promise<string | null>;
23
+ setItem(key: string, value: string): Promise<void>;
24
+ deleteItem(key: string): Promise<void>;
25
+ }
26
+
27
+ /** In-memory fallback when expo-secure-store is not available. */
28
+ const memoryStore = new Map<string, string>();
29
+
30
+ const memoryAdapter: StorageAdapter = {
31
+ async getItem(key) {
32
+ return memoryStore.get(key) ?? null;
33
+ },
34
+ async setItem(key, value) {
35
+ memoryStore.set(key, value);
36
+ },
37
+ async deleteItem(key) {
38
+ memoryStore.delete(key);
39
+ },
40
+ };
41
+
42
+ let _adapter: StorageAdapter | null = null;
43
+
44
+ function getAdapter(): StorageAdapter {
45
+ if (_adapter) return _adapter;
46
+
47
+ try {
48
+ // Dynamic import to keep expo-secure-store truly optional.
49
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
50
+ const SecureStore = require('expo-secure-store');
51
+ if (SecureStore?.setItemAsync) {
52
+ _adapter = {
53
+ getItem: (key: string) => SecureStore.getItemAsync(key),
54
+ setItem: (key: string, value: string) =>
55
+ SecureStore.setItemAsync(key, value),
56
+ deleteItem: (key: string) => SecureStore.deleteItemAsync(key),
57
+ };
58
+ return _adapter;
59
+ }
60
+ } catch {
61
+ // expo-secure-store not available — use memory fallback.
62
+ }
63
+
64
+ _adapter = memoryAdapter;
65
+ return _adapter;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Public API
70
+ // ---------------------------------------------------------------------------
71
+
72
+ /** Persist session to secure storage (or memory fallback). */
73
+ export async function saveSession(
74
+ workspaceId: string,
75
+ session: Session,
76
+ ): Promise<void> {
77
+ const adapter = getAdapter();
78
+ await adapter.setItem(storeKey(workspaceId), JSON.stringify(session));
79
+ }
80
+
81
+ /** Retrieve persisted session, or null if none exists. */
82
+ export async function loadSession(
83
+ workspaceId: string,
84
+ ): Promise<Session | null> {
85
+ const adapter = getAdapter();
86
+ try {
87
+ const raw = await adapter.getItem(storeKey(workspaceId));
88
+ if (!raw) return null;
89
+
90
+ const session: Session = JSON.parse(raw);
91
+
92
+ // Validate required fields.
93
+ if (
94
+ typeof session.token !== 'string' ||
95
+ typeof session.contactId !== 'string' ||
96
+ typeof session.expiresAt !== 'string'
97
+ ) {
98
+ console.warn(
99
+ '[@parlr/react-native] Stored session has invalid shape, clearing.',
100
+ );
101
+ await clearSession(workspaceId);
102
+ return null;
103
+ }
104
+
105
+ return session;
106
+ } catch (err) {
107
+ // Corrupted data — clear and return null.
108
+ console.warn(
109
+ '[@parlr/react-native] Failed to load session, clearing:',
110
+ err,
111
+ );
112
+ await clearSession(workspaceId);
113
+ return null;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Returns true when the session token has not yet expired.
119
+ * Adds a 60-second safety margin to avoid edge-case failures.
120
+ */
121
+ export function isSessionValid(session: Session): boolean {
122
+ try {
123
+ const expiresAt = new Date(session.expiresAt).getTime();
124
+ if (isNaN(expiresAt)) {
125
+ console.warn(
126
+ '[@parlr/react-native] Invalid expiresAt date:',
127
+ session.expiresAt,
128
+ );
129
+ return false;
130
+ }
131
+ const margin = 60_000; // 60 s
132
+ return Date.now() < expiresAt - margin;
133
+ } catch (err) {
134
+ console.warn(
135
+ '[@parlr/react-native] Error checking session validity:',
136
+ err,
137
+ );
138
+ return false;
139
+ }
140
+ }
141
+
142
+ /** Delete persisted session for a workspace. */
143
+ export async function clearSession(workspaceId: string): Promise<void> {
144
+ const adapter = getAdapter();
145
+ try {
146
+ await adapter.deleteItem(storeKey(workspaceId));
147
+ } catch {
148
+ // Best-effort — nothing to do if deletion fails.
149
+ }
150
+ }
151
+
152
+ /** Reset the storage adapter (for testing). */
153
+ export function _resetAdapter(): void {
154
+ _adapter = null;
155
+ memoryStore.clear();
156
+ }
@@ -0,0 +1,133 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Parlr React Native SDK - Theming System
3
+ // ---------------------------------------------------------------------------
4
+
5
+ export interface ParlrTheme {
6
+ colors: {
7
+ primary: string;
8
+ primaryText: string;
9
+ background: string;
10
+ surface: string;
11
+ surfaceDark: string;
12
+ text: string;
13
+ textSecondary: string;
14
+ border: string;
15
+ success: string;
16
+ error: string;
17
+ agentBubble: string;
18
+ agentBubbleDark: string;
19
+ agentText: string;
20
+ agentTextDark: string;
21
+ contactBubble: string;
22
+ contactText: string;
23
+ };
24
+ borderRadius: {
25
+ bubble: number;
26
+ input: number;
27
+ button: number;
28
+ avatar: number;
29
+ };
30
+ spacing: {
31
+ xs: number;
32
+ sm: number;
33
+ md: number;
34
+ lg: number;
35
+ xl: number;
36
+ };
37
+ typography: {
38
+ headerSize: number;
39
+ bodySize: number;
40
+ captionSize: number;
41
+ };
42
+ }
43
+
44
+ export const defaultLightTheme: ParlrTheme = {
45
+ colors: {
46
+ primary: '#6366F1',
47
+ primaryText: '#FFFFFF',
48
+ background: '#FFFFFF',
49
+ surface: '#F9FAFB',
50
+ surfaceDark: '#F3F4F6',
51
+ text: '#111827',
52
+ textSecondary: '#6B7280',
53
+ border: '#E5E7EB',
54
+ success: '#10B981',
55
+ error: '#EF4444',
56
+ agentBubble: '#F3F4F6',
57
+ agentBubbleDark: '#E5E7EB',
58
+ agentText: '#111827',
59
+ agentTextDark: '#111827',
60
+ contactBubble: '#6366F1',
61
+ contactText: '#FFFFFF',
62
+ },
63
+ borderRadius: {
64
+ bubble: 16,
65
+ input: 12,
66
+ button: 8,
67
+ avatar: 20,
68
+ },
69
+ spacing: {
70
+ xs: 4,
71
+ sm: 8,
72
+ md: 16,
73
+ lg: 24,
74
+ xl: 32,
75
+ },
76
+ typography: {
77
+ headerSize: 18,
78
+ bodySize: 15,
79
+ captionSize: 12,
80
+ },
81
+ };
82
+
83
+ export const defaultDarkTheme: ParlrTheme = {
84
+ colors: {
85
+ primary: '#818CF8',
86
+ primaryText: '#FFFFFF',
87
+ background: '#111827',
88
+ surface: '#1F2937',
89
+ surfaceDark: '#374151',
90
+ text: '#F9FAFB',
91
+ textSecondary: '#9CA3AF',
92
+ border: '#374151',
93
+ success: '#34D399',
94
+ error: '#F87171',
95
+ agentBubble: '#1F2937',
96
+ agentBubbleDark: '#374151',
97
+ agentText: '#F9FAFB',
98
+ agentTextDark: '#F9FAFB',
99
+ contactBubble: '#818CF8',
100
+ contactText: '#FFFFFF',
101
+ },
102
+ borderRadius: {
103
+ bubble: 16,
104
+ input: 12,
105
+ button: 8,
106
+ avatar: 20,
107
+ },
108
+ spacing: {
109
+ xs: 4,
110
+ sm: 8,
111
+ md: 16,
112
+ lg: 24,
113
+ xl: 32,
114
+ },
115
+ typography: {
116
+ headerSize: 18,
117
+ bodySize: 15,
118
+ captionSize: 12,
119
+ },
120
+ };
121
+
122
+ /** Deep-merge a base theme with partial overrides. */
123
+ export function mergeTheme(
124
+ base: ParlrTheme,
125
+ overrides: Partial<ParlrTheme>,
126
+ ): ParlrTheme {
127
+ return {
128
+ colors: { ...base.colors, ...overrides.colors },
129
+ borderRadius: { ...base.borderRadius, ...overrides.borderRadius },
130
+ spacing: { ...base.spacing, ...overrides.spacing },
131
+ typography: { ...base.typography, ...overrides.typography },
132
+ };
133
+ }
@@ -0,0 +1,237 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Parlr React Native SDK - Core Types
3
+ // ---------------------------------------------------------------------------
4
+
5
+ import type { ParlrError } from './errors';
6
+ import type { ParlrTheme } from './theme';
7
+
8
+ /** SDK configuration. Only `workspaceId` is required. */
9
+ export interface ParlrConfig {
10
+ /** Unique workspace identifier (e.g. "ws_abc123"). */
11
+ workspaceId: string;
12
+ /** REST API base URL. Defaults to https://api.parlr.chat/api/v1/widget */
13
+ apiBaseUrl?: string;
14
+ /** WebSocket endpoint. Defaults to wss://ws.parlr.chat/ws */
15
+ wsUrl?: string;
16
+ /** Locale code (BCP-47). Defaults to "fr". */
17
+ locale?: string;
18
+ /** Enable verbose console logging. Defaults to false. */
19
+ debug?: boolean;
20
+ /** Global error callback for the host app to monitor SDK errors. */
21
+ onError?: (error: ParlrError) => void;
22
+ /** HMAC identity verification token for secure identification. */
23
+ identityToken?: string;
24
+ /** Custom theme overrides. Merged with the default light/dark theme. */
25
+ theme?: Partial<ParlrTheme>;
26
+ }
27
+
28
+ /** Resolved configuration with all defaults applied. */
29
+ export interface ResolvedConfig {
30
+ workspaceId: string;
31
+ apiBaseUrl: string;
32
+ wsUrl: string;
33
+ locale: string;
34
+ debug: boolean;
35
+ onError?: (error: ParlrError) => void;
36
+ identityToken?: string;
37
+ }
38
+
39
+ /** Visitor / contact identity passed by the host app. */
40
+ export interface ParlrUser {
41
+ email?: string;
42
+ name?: string;
43
+ firstName?: string;
44
+ lastName?: string;
45
+ externalId?: string;
46
+ phone?: string;
47
+ company?: string;
48
+ customAttributes?: Record<string, unknown>;
49
+ }
50
+
51
+ /** Persisted session returned by the widget API. */
52
+ export interface Session {
53
+ token: string;
54
+ contactId: string;
55
+ workspaceId: string;
56
+ expiresAt: string;
57
+ }
58
+
59
+ /** Conversation summary. */
60
+ export interface Conversation {
61
+ id: string;
62
+ status: 'open' | 'resolved' | 'pending' | 'closed';
63
+ subject: string | null;
64
+ lastMessageAt: string | null;
65
+ unreadCount: number;
66
+ assignee?: {
67
+ id: string;
68
+ name: string;
69
+ avatarUrl?: string;
70
+ } | null;
71
+ }
72
+
73
+ /** Attachment on a message. */
74
+ export interface Attachment {
75
+ id: string;
76
+ name: string;
77
+ url: string;
78
+ contentType: string;
79
+ size: number;
80
+ }
81
+
82
+ /** Content type of a message. */
83
+ export type MessageContentType = 'text' | 'image' | 'file' | 'rich';
84
+
85
+ /** CSAT rating request. */
86
+ export interface RatingRequest {
87
+ score: number;
88
+ comment?: string;
89
+ }
90
+
91
+ /** Chat message within a conversation. */
92
+ export interface Message {
93
+ id: string;
94
+ conversationId: string;
95
+ senderType: 'contact' | 'agent';
96
+ senderName?: string;
97
+ senderAvatarUrl?: string;
98
+ content: string;
99
+ createdAt: string;
100
+ /** Client-generated UUID used for optimistic updates and idempotency. */
101
+ clientId?: string;
102
+ /** Delivery status for optimistic messages. */
103
+ status?: 'sending' | 'sent' | 'failed' | 'read';
104
+ /** File/media attachments. */
105
+ attachments?: Attachment[];
106
+ /** Content type of the message body. */
107
+ contentType?: MessageContentType;
108
+ /** Rich content metadata (cards, buttons, etc.). */
109
+ metadata?: Record<string, unknown>;
110
+ }
111
+
112
+ // ---------------------------------------------------------------------------
113
+ // WebSocket event types — discriminated unions for type safety
114
+ // ---------------------------------------------------------------------------
115
+
116
+ export type WsOutgoingType =
117
+ | 'auth'
118
+ | 'send_message'
119
+ | 'typing_start'
120
+ | 'typing_stop'
121
+ | 'message_seen'
122
+ | 'ping';
123
+
124
+ export type WsIncomingType =
125
+ | 'auth_ok'
126
+ | 'auth_error'
127
+ | 'new_message'
128
+ | 'typing_start'
129
+ | 'typing_stop'
130
+ | 'message_seen'
131
+ | 'conversation_updated'
132
+ | 'pong'
133
+ | 'disconnected'
134
+ | 'error';
135
+
136
+ export interface WsOutgoingPayload {
137
+ type: WsOutgoingType;
138
+ payload?: Record<string, unknown>;
139
+ }
140
+
141
+ export interface WsIncomingPayload {
142
+ type: WsIncomingType;
143
+ payload?: Record<string, unknown>;
144
+ }
145
+
146
+ // ---------------------------------------------------------------------------
147
+ // Typed WebSocket event payloads (incoming)
148
+ // ---------------------------------------------------------------------------
149
+
150
+ export interface WsNewMessagePayload {
151
+ id: string;
152
+ conversationId: string;
153
+ senderType: 'contact' | 'agent';
154
+ senderName?: string;
155
+ senderAvatarUrl?: string;
156
+ content: string;
157
+ createdAt: string;
158
+ clientId?: string;
159
+ }
160
+
161
+ export interface WsTypingPayload {
162
+ conversationId: string;
163
+ senderType?: 'agent' | 'contact';
164
+ senderName?: string;
165
+ }
166
+
167
+ export interface WsMessageSeenPayload {
168
+ conversationId: string;
169
+ messageId: string;
170
+ seenBy: string;
171
+ }
172
+
173
+ export interface WsConversationUpdatedPayload {
174
+ conversationId: string;
175
+ status?: 'open' | 'resolved' | 'pending' | 'closed';
176
+ assignee?: { id: string; name: string } | null;
177
+ }
178
+
179
+ export interface WsAuthOkPayload {
180
+ contactId: string;
181
+ }
182
+
183
+ export interface WsAuthErrorPayload {
184
+ code?: number;
185
+ reason?: string;
186
+ message?: string;
187
+ }
188
+
189
+ export interface WsErrorPayload {
190
+ code?: string;
191
+ message?: string;
192
+ }
193
+
194
+ /** Type-safe mapping from incoming WS event type to its payload. */
195
+ export interface WsEventMap {
196
+ auth_ok: WsAuthOkPayload;
197
+ auth_error: WsAuthErrorPayload;
198
+ new_message: WsNewMessagePayload;
199
+ typing_start: WsTypingPayload;
200
+ typing_stop: WsTypingPayload;
201
+ message_seen: WsMessageSeenPayload;
202
+ conversation_updated: WsConversationUpdatedPayload;
203
+ pong: Record<string, never>;
204
+ disconnected: { code?: number; reason?: string };
205
+ error: WsErrorPayload;
206
+ }
207
+
208
+ // ---------------------------------------------------------------------------
209
+ // API response wrappers
210
+ // ---------------------------------------------------------------------------
211
+
212
+ export interface PaginatedResponse<T> {
213
+ data: T[];
214
+ meta: {
215
+ page: number;
216
+ perPage: number;
217
+ total: number;
218
+ hasMore: boolean;
219
+ };
220
+ }
221
+
222
+ // ---------------------------------------------------------------------------
223
+ // Provider / context shape
224
+ // ---------------------------------------------------------------------------
225
+
226
+ export interface ParlrContextValue {
227
+ config: ResolvedConfig;
228
+ session: Session | null;
229
+ isReady: boolean;
230
+ isConnected: boolean;
231
+ conversations: Conversation[];
232
+ unreadCount: number;
233
+ identify: (user: ParlrUser) => Promise<void>;
234
+ refreshConversations: () => Promise<void>;
235
+ /** Resolved theme (light or dark, merged with user overrides). */
236
+ theme: ParlrTheme;
237
+ }