@pocketping/widget 0.1.0 → 0.3.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/LICENSE +21 -0
- package/README.md +89 -2
- package/dist/index.d.mts +199 -4
- package/dist/index.d.ts +199 -4
- package/dist/index.js +292 -14
- package/dist/index.mjs +284 -13
- package/dist/pocketping.min.global.js +329 -0
- package/package.json +12 -8
- package/dist/index.global.js +0 -1475
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 PocketPing Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Embeddable chat widget for PocketPing. Drop-in customer support chat that connec
|
|
|
7
7
|
### Via CDN (Recommended)
|
|
8
8
|
|
|
9
9
|
```html
|
|
10
|
-
<script src="https://cdn.
|
|
10
|
+
<script src="https://cdn.pocketping.io/widget.js"></script>
|
|
11
11
|
<script>
|
|
12
12
|
PocketPing.init({
|
|
13
13
|
endpoint: 'https://yoursite.com/pocketping'
|
|
@@ -260,18 +260,96 @@ PocketPing.close();
|
|
|
260
260
|
// Toggle the chat
|
|
261
261
|
PocketPing.toggle();
|
|
262
262
|
|
|
263
|
+
// Send a message programmatically
|
|
264
|
+
PocketPing.sendMessage('Hello!');
|
|
265
|
+
|
|
263
266
|
// Destroy the widget
|
|
264
267
|
PocketPing.destroy();
|
|
265
268
|
```
|
|
266
269
|
|
|
267
270
|
---
|
|
268
271
|
|
|
272
|
+
## Custom Events
|
|
273
|
+
|
|
274
|
+
PocketPing supports bidirectional custom events between your website and the backend. This enables powerful interactions like triggering alerts when users take specific actions.
|
|
275
|
+
|
|
276
|
+
### Triggering Events (Widget → Backend)
|
|
277
|
+
|
|
278
|
+
Send events to your backend when users perform actions:
|
|
279
|
+
|
|
280
|
+
```javascript
|
|
281
|
+
// Notify when user clicks pricing
|
|
282
|
+
PocketPing.trigger('clicked_pricing', { plan: 'pro', source: 'header' });
|
|
283
|
+
|
|
284
|
+
// Track user interactions
|
|
285
|
+
PocketPing.trigger('viewed_demo');
|
|
286
|
+
PocketPing.trigger('downloaded_pdf', { name: 'whitepaper.pdf' });
|
|
287
|
+
|
|
288
|
+
// Report errors
|
|
289
|
+
PocketPing.trigger('error_occurred', { code: 500, page: window.location.pathname });
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
Events are forwarded to your backend and displayed in Telegram/Discord/Slack with full context.
|
|
293
|
+
|
|
294
|
+
### Listening for Events (Backend → Widget)
|
|
295
|
+
|
|
296
|
+
Your backend can send events to the widget. Subscribe to handle them:
|
|
297
|
+
|
|
298
|
+
```javascript
|
|
299
|
+
// Subscribe to an event
|
|
300
|
+
const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
|
|
301
|
+
showPopup(`Special offer: ${data.discount}% off!`);
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// Unsubscribe when done
|
|
305
|
+
unsubscribe();
|
|
306
|
+
|
|
307
|
+
// Or use offEvent
|
|
308
|
+
PocketPing.onEvent('announcement', handleAnnouncement);
|
|
309
|
+
PocketPing.offEvent('announcement', handleAnnouncement);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Event Callback
|
|
313
|
+
|
|
314
|
+
You can also use an `onEvent` callback in the init config:
|
|
315
|
+
|
|
316
|
+
```javascript
|
|
317
|
+
PocketPing.init({
|
|
318
|
+
endpoint: 'https://yoursite.com/pocketping',
|
|
319
|
+
onEvent: (event) => {
|
|
320
|
+
console.log('Received event:', event.name, event.data);
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Use Cases
|
|
326
|
+
|
|
327
|
+
| Event | Use Case |
|
|
328
|
+
|-------|----------|
|
|
329
|
+
| `clicked_pricing` | Alert sales team when visitor shows interest |
|
|
330
|
+
| `error_spike` | Get notified of frontend errors |
|
|
331
|
+
| `cart_abandoned` | Trigger follow-up message |
|
|
332
|
+
| `show_offer` | Display personalized offer |
|
|
333
|
+
| `request_demo` | Open demo scheduling modal |
|
|
334
|
+
| `announcement` | Show system-wide notification |
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
269
338
|
## TypeScript Support
|
|
270
339
|
|
|
271
340
|
Full TypeScript definitions are included:
|
|
272
341
|
|
|
273
342
|
```typescript
|
|
274
|
-
import {
|
|
343
|
+
import {
|
|
344
|
+
init,
|
|
345
|
+
trigger,
|
|
346
|
+
onEvent,
|
|
347
|
+
offEvent,
|
|
348
|
+
PocketPingConfig,
|
|
349
|
+
Message,
|
|
350
|
+
CustomEvent,
|
|
351
|
+
CustomEventHandler
|
|
352
|
+
} from '@pocketping/widget';
|
|
275
353
|
|
|
276
354
|
const config: PocketPingConfig = {
|
|
277
355
|
endpoint: 'https://yoursite.com/pocketping',
|
|
@@ -281,6 +359,15 @@ const config: PocketPingConfig = {
|
|
|
281
359
|
};
|
|
282
360
|
|
|
283
361
|
init(config);
|
|
362
|
+
|
|
363
|
+
// Type-safe events
|
|
364
|
+
trigger('clicked_pricing', { plan: 'pro' });
|
|
365
|
+
|
|
366
|
+
const handler: CustomEventHandler = (data, event: CustomEvent) => {
|
|
367
|
+
console.log(event.name, data);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
onEvent('show_offer', handler);
|
|
284
371
|
```
|
|
285
372
|
|
|
286
373
|
---
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
interface PocketPingConfig {
|
|
2
|
-
/** Your backend endpoint (e.g., "https://yoursite.com/pocketping") */
|
|
3
|
-
endpoint
|
|
2
|
+
/** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
|
|
3
|
+
endpoint?: string;
|
|
4
|
+
/** Project ID for SaaS users (e.g., "proj_xxxxxxxxxxxxx") - from dashboard */
|
|
5
|
+
projectId?: string;
|
|
4
6
|
/** Company/operator name displayed in header */
|
|
5
7
|
operatorName?: string;
|
|
6
8
|
/** Operator/company avatar URL (displayed in header) */
|
|
@@ -59,6 +61,8 @@ interface PocketPingConfig {
|
|
|
59
61
|
onConnect?: (sessionId: string) => void;
|
|
60
62
|
/** Called when connection fails */
|
|
61
63
|
onError?: (error: Error) => void;
|
|
64
|
+
/** Called when a version mismatch is detected */
|
|
65
|
+
onVersionWarning?: (warning: VersionWarning) => void;
|
|
62
66
|
}
|
|
63
67
|
type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read';
|
|
64
68
|
interface Message {
|
|
@@ -78,6 +82,8 @@ interface Session {
|
|
|
78
82
|
visitorId: string;
|
|
79
83
|
operatorOnline: boolean;
|
|
80
84
|
messages: Message[];
|
|
85
|
+
/** User identity if identified via PocketPing.identify() */
|
|
86
|
+
identity?: UserIdentity;
|
|
81
87
|
}
|
|
82
88
|
interface PresenceResponse {
|
|
83
89
|
online: boolean;
|
|
@@ -89,6 +95,58 @@ interface PresenceResponse {
|
|
|
89
95
|
aiEnabled?: boolean;
|
|
90
96
|
aiActiveAfter?: number;
|
|
91
97
|
}
|
|
98
|
+
type VersionWarningSeverity = 'info' | 'warning' | 'error';
|
|
99
|
+
interface VersionWarning {
|
|
100
|
+
/** Severity level of the warning */
|
|
101
|
+
severity: VersionWarningSeverity;
|
|
102
|
+
/** Human-readable warning message */
|
|
103
|
+
message: string;
|
|
104
|
+
/** Current widget version */
|
|
105
|
+
currentVersion: string;
|
|
106
|
+
/** Minimum supported version (if applicable) */
|
|
107
|
+
minVersion?: string;
|
|
108
|
+
/** Latest available version (if applicable) */
|
|
109
|
+
latestVersion?: string;
|
|
110
|
+
/** Whether the widget should still function */
|
|
111
|
+
canContinue: boolean;
|
|
112
|
+
/** URL to upgrade instructions */
|
|
113
|
+
upgradeUrl?: string;
|
|
114
|
+
}
|
|
115
|
+
/** Custom event sent from widget to backend or vice versa */
|
|
116
|
+
interface CustomEvent {
|
|
117
|
+
/** Event name (e.g., 'clicked_pricing', 'show_offer') */
|
|
118
|
+
name: string;
|
|
119
|
+
/** Event payload */
|
|
120
|
+
data?: Record<string, unknown>;
|
|
121
|
+
/** Timestamp of the event */
|
|
122
|
+
timestamp: string;
|
|
123
|
+
}
|
|
124
|
+
/** Handler for custom events */
|
|
125
|
+
type CustomEventHandler = (data: Record<string, unknown> | undefined, event: CustomEvent) => void;
|
|
126
|
+
/**
|
|
127
|
+
* User identity data for identifying visitors
|
|
128
|
+
* @example
|
|
129
|
+
* PocketPing.identify({
|
|
130
|
+
* id: 'user_123',
|
|
131
|
+
* email: 'john@example.com',
|
|
132
|
+
* name: 'John Doe',
|
|
133
|
+
* plan: 'pro',
|
|
134
|
+
* company: 'Acme Inc'
|
|
135
|
+
* })
|
|
136
|
+
*/
|
|
137
|
+
interface UserIdentity {
|
|
138
|
+
/** Required unique user identifier */
|
|
139
|
+
id: string;
|
|
140
|
+
/** User's email address */
|
|
141
|
+
email?: string;
|
|
142
|
+
/** User's display name */
|
|
143
|
+
name?: string;
|
|
144
|
+
/** Any custom fields (plan, company, etc.) */
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
type ResolvedPocketPingConfig = Omit<PocketPingConfig, 'endpoint'> & {
|
|
148
|
+
endpoint: string;
|
|
149
|
+
};
|
|
92
150
|
|
|
93
151
|
type Listener<T> = (data: T) => void;
|
|
94
152
|
declare class PocketPingClient {
|
|
@@ -97,10 +155,11 @@ declare class PocketPingClient {
|
|
|
97
155
|
private ws;
|
|
98
156
|
private isOpen;
|
|
99
157
|
private listeners;
|
|
158
|
+
private customEventHandlers;
|
|
100
159
|
private reconnectAttempts;
|
|
101
160
|
private maxReconnectAttempts;
|
|
102
161
|
private reconnectTimeout;
|
|
103
|
-
constructor(config:
|
|
162
|
+
constructor(config: ResolvedPocketPingConfig);
|
|
104
163
|
connect(): Promise<Session>;
|
|
105
164
|
disconnect(): void;
|
|
106
165
|
sendMessage(content: string): Promise<Message>;
|
|
@@ -108,6 +167,33 @@ declare class PocketPingClient {
|
|
|
108
167
|
sendTyping(isTyping?: boolean): Promise<void>;
|
|
109
168
|
sendReadStatus(messageIds: string[], status: MessageStatus): Promise<void>;
|
|
110
169
|
getPresence(): Promise<PresenceResponse>;
|
|
170
|
+
/**
|
|
171
|
+
* Identify the current user with metadata
|
|
172
|
+
* Call after user logs in or when user data becomes available
|
|
173
|
+
* @param identity - User identity data with required id field
|
|
174
|
+
* @example
|
|
175
|
+
* PocketPing.identify({
|
|
176
|
+
* id: 'user_123',
|
|
177
|
+
* email: 'john@example.com',
|
|
178
|
+
* name: 'John Doe',
|
|
179
|
+
* plan: 'pro',
|
|
180
|
+
* company: 'Acme Inc'
|
|
181
|
+
* })
|
|
182
|
+
*/
|
|
183
|
+
identify(identity: UserIdentity): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* Reset the user identity and optionally start a new session
|
|
186
|
+
* Call on user logout to clear user data
|
|
187
|
+
* @param options - Optional settings: { newSession: boolean }
|
|
188
|
+
*/
|
|
189
|
+
reset(options?: {
|
|
190
|
+
newSession?: boolean;
|
|
191
|
+
}): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Get the current user identity
|
|
194
|
+
* @returns UserIdentity or null if not identified
|
|
195
|
+
*/
|
|
196
|
+
getIdentity(): UserIdentity | null;
|
|
111
197
|
getSession(): Session | null;
|
|
112
198
|
getMessages(): Message[];
|
|
113
199
|
isConnected(): boolean;
|
|
@@ -116,14 +202,45 @@ declare class PocketPingClient {
|
|
|
116
202
|
toggleOpen(): void;
|
|
117
203
|
on<T>(event: string, listener: Listener<T>): () => void;
|
|
118
204
|
private emit;
|
|
205
|
+
/**
|
|
206
|
+
* Trigger a custom event to the backend
|
|
207
|
+
* @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
|
|
208
|
+
* @param data - Optional payload to send with the event
|
|
209
|
+
* @example
|
|
210
|
+
* PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
|
|
211
|
+
*/
|
|
212
|
+
trigger(eventName: string, data?: Record<string, unknown>): void;
|
|
213
|
+
/**
|
|
214
|
+
* Subscribe to custom events from the backend
|
|
215
|
+
* @param eventName - The name of the event to listen for (e.g., 'show_offer', 'open_chat')
|
|
216
|
+
* @param handler - Callback function when event is received
|
|
217
|
+
* @returns Unsubscribe function
|
|
218
|
+
* @example
|
|
219
|
+
* const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
|
|
220
|
+
* showPopup(data.message)
|
|
221
|
+
* })
|
|
222
|
+
*/
|
|
223
|
+
onEvent(eventName: string, handler: CustomEventHandler): () => void;
|
|
224
|
+
/**
|
|
225
|
+
* Unsubscribe from a custom event
|
|
226
|
+
* @param eventName - The name of the event
|
|
227
|
+
* @param handler - The handler to remove
|
|
228
|
+
*/
|
|
229
|
+
offEvent(eventName: string, handler: CustomEventHandler): void;
|
|
230
|
+
private emitCustomEvent;
|
|
119
231
|
private connectWebSocket;
|
|
120
232
|
private handleWebSocketEvent;
|
|
233
|
+
private handleVersionWarning;
|
|
121
234
|
private scheduleReconnect;
|
|
122
235
|
private startPolling;
|
|
123
236
|
private fetch;
|
|
237
|
+
private checkVersionHeaders;
|
|
124
238
|
private getOrCreateVisitorId;
|
|
125
239
|
private getStoredSessionId;
|
|
126
240
|
private storeSessionId;
|
|
241
|
+
private getStoredIdentity;
|
|
242
|
+
private storeIdentity;
|
|
243
|
+
private clearIdentity;
|
|
127
244
|
private generateId;
|
|
128
245
|
}
|
|
129
246
|
|
|
@@ -133,6 +250,77 @@ declare function open(): void;
|
|
|
133
250
|
declare function close(): void;
|
|
134
251
|
declare function toggle(): void;
|
|
135
252
|
declare function sendMessage(content: string): Promise<Message>;
|
|
253
|
+
/**
|
|
254
|
+
* Trigger a custom event to the backend
|
|
255
|
+
* @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
|
|
256
|
+
* @param data - Optional payload to send with the event
|
|
257
|
+
* @example
|
|
258
|
+
* PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
|
|
259
|
+
*/
|
|
260
|
+
declare function trigger(eventName: string, data?: Record<string, unknown>): void;
|
|
261
|
+
/**
|
|
262
|
+
* Subscribe to custom events from the backend
|
|
263
|
+
* @param eventName - The name of the event to listen for
|
|
264
|
+
* @param handler - Callback function when event is received
|
|
265
|
+
* @returns Unsubscribe function
|
|
266
|
+
* @example
|
|
267
|
+
* const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
|
|
268
|
+
* showPopup(data.message)
|
|
269
|
+
* })
|
|
270
|
+
*/
|
|
271
|
+
declare function onEvent(eventName: string, handler: CustomEventHandler): () => void;
|
|
272
|
+
/**
|
|
273
|
+
* Unsubscribe from a custom event
|
|
274
|
+
* @param eventName - The name of the event
|
|
275
|
+
* @param handler - The handler to remove
|
|
276
|
+
*/
|
|
277
|
+
declare function offEvent(eventName: string, handler: CustomEventHandler): void;
|
|
278
|
+
/**
|
|
279
|
+
* Identify the current user with metadata
|
|
280
|
+
* Call after user logs in or when user data becomes available
|
|
281
|
+
* @param identity - User identity data with required id field
|
|
282
|
+
* @example
|
|
283
|
+
* PocketPing.identify({
|
|
284
|
+
* id: 'user_123',
|
|
285
|
+
* email: 'john@example.com',
|
|
286
|
+
* name: 'John Doe',
|
|
287
|
+
* plan: 'pro',
|
|
288
|
+
* company: 'Acme Inc'
|
|
289
|
+
* })
|
|
290
|
+
*/
|
|
291
|
+
declare function identify(identity: UserIdentity): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Reset the user identity and optionally start a new session
|
|
294
|
+
* Call on user logout to clear user data
|
|
295
|
+
* @param options - Optional settings: { newSession: boolean }
|
|
296
|
+
* @example
|
|
297
|
+
* // Clear identity but keep session
|
|
298
|
+
* PocketPing.reset()
|
|
299
|
+
*
|
|
300
|
+
* // Clear everything and start fresh
|
|
301
|
+
* PocketPing.reset({ newSession: true })
|
|
302
|
+
*/
|
|
303
|
+
declare function reset(options?: {
|
|
304
|
+
newSession?: boolean;
|
|
305
|
+
}): Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* Get the current user identity
|
|
308
|
+
* @returns UserIdentity or null if not identified
|
|
309
|
+
*/
|
|
310
|
+
declare function getIdentity(): UserIdentity | null;
|
|
311
|
+
/**
|
|
312
|
+
* Subscribe to internal widget events
|
|
313
|
+
* @param eventName - Event name: 'versionWarning', 'message', 'connect', 'typing', etc.
|
|
314
|
+
* @param handler - Callback function
|
|
315
|
+
* @returns Unsubscribe function
|
|
316
|
+
* @example
|
|
317
|
+
* PocketPing.on('versionWarning', (warning) => {
|
|
318
|
+
* if (warning.severity === 'error') {
|
|
319
|
+
* showUpgradeNotice(warning.message);
|
|
320
|
+
* }
|
|
321
|
+
* })
|
|
322
|
+
*/
|
|
323
|
+
declare function on<T>(eventName: string, handler: (data: T) => void): () => void;
|
|
136
324
|
declare const _default: {
|
|
137
325
|
init: typeof init;
|
|
138
326
|
destroy: typeof destroy;
|
|
@@ -140,6 +328,13 @@ declare const _default: {
|
|
|
140
328
|
close: typeof close;
|
|
141
329
|
toggle: typeof toggle;
|
|
142
330
|
sendMessage: typeof sendMessage;
|
|
331
|
+
trigger: typeof trigger;
|
|
332
|
+
onEvent: typeof onEvent;
|
|
333
|
+
offEvent: typeof offEvent;
|
|
334
|
+
on: typeof on;
|
|
335
|
+
identify: typeof identify;
|
|
336
|
+
reset: typeof reset;
|
|
337
|
+
getIdentity: typeof getIdentity;
|
|
143
338
|
};
|
|
144
339
|
|
|
145
|
-
export { type Message, type PocketPingConfig, close, _default as default, destroy, init, open, sendMessage, toggle };
|
|
340
|
+
export { type CustomEvent, type CustomEventHandler, type Message, type PocketPingConfig, type UserIdentity, type VersionWarning, close, _default as default, destroy, getIdentity, identify, init, offEvent, on, onEvent, open, reset, sendMessage, toggle, trigger };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
interface PocketPingConfig {
|
|
2
|
-
/** Your backend endpoint (e.g., "https://yoursite.com/pocketping") */
|
|
3
|
-
endpoint
|
|
2
|
+
/** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
|
|
3
|
+
endpoint?: string;
|
|
4
|
+
/** Project ID for SaaS users (e.g., "proj_xxxxxxxxxxxxx") - from dashboard */
|
|
5
|
+
projectId?: string;
|
|
4
6
|
/** Company/operator name displayed in header */
|
|
5
7
|
operatorName?: string;
|
|
6
8
|
/** Operator/company avatar URL (displayed in header) */
|
|
@@ -59,6 +61,8 @@ interface PocketPingConfig {
|
|
|
59
61
|
onConnect?: (sessionId: string) => void;
|
|
60
62
|
/** Called when connection fails */
|
|
61
63
|
onError?: (error: Error) => void;
|
|
64
|
+
/** Called when a version mismatch is detected */
|
|
65
|
+
onVersionWarning?: (warning: VersionWarning) => void;
|
|
62
66
|
}
|
|
63
67
|
type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read';
|
|
64
68
|
interface Message {
|
|
@@ -78,6 +82,8 @@ interface Session {
|
|
|
78
82
|
visitorId: string;
|
|
79
83
|
operatorOnline: boolean;
|
|
80
84
|
messages: Message[];
|
|
85
|
+
/** User identity if identified via PocketPing.identify() */
|
|
86
|
+
identity?: UserIdentity;
|
|
81
87
|
}
|
|
82
88
|
interface PresenceResponse {
|
|
83
89
|
online: boolean;
|
|
@@ -89,6 +95,58 @@ interface PresenceResponse {
|
|
|
89
95
|
aiEnabled?: boolean;
|
|
90
96
|
aiActiveAfter?: number;
|
|
91
97
|
}
|
|
98
|
+
type VersionWarningSeverity = 'info' | 'warning' | 'error';
|
|
99
|
+
interface VersionWarning {
|
|
100
|
+
/** Severity level of the warning */
|
|
101
|
+
severity: VersionWarningSeverity;
|
|
102
|
+
/** Human-readable warning message */
|
|
103
|
+
message: string;
|
|
104
|
+
/** Current widget version */
|
|
105
|
+
currentVersion: string;
|
|
106
|
+
/** Minimum supported version (if applicable) */
|
|
107
|
+
minVersion?: string;
|
|
108
|
+
/** Latest available version (if applicable) */
|
|
109
|
+
latestVersion?: string;
|
|
110
|
+
/** Whether the widget should still function */
|
|
111
|
+
canContinue: boolean;
|
|
112
|
+
/** URL to upgrade instructions */
|
|
113
|
+
upgradeUrl?: string;
|
|
114
|
+
}
|
|
115
|
+
/** Custom event sent from widget to backend or vice versa */
|
|
116
|
+
interface CustomEvent {
|
|
117
|
+
/** Event name (e.g., 'clicked_pricing', 'show_offer') */
|
|
118
|
+
name: string;
|
|
119
|
+
/** Event payload */
|
|
120
|
+
data?: Record<string, unknown>;
|
|
121
|
+
/** Timestamp of the event */
|
|
122
|
+
timestamp: string;
|
|
123
|
+
}
|
|
124
|
+
/** Handler for custom events */
|
|
125
|
+
type CustomEventHandler = (data: Record<string, unknown> | undefined, event: CustomEvent) => void;
|
|
126
|
+
/**
|
|
127
|
+
* User identity data for identifying visitors
|
|
128
|
+
* @example
|
|
129
|
+
* PocketPing.identify({
|
|
130
|
+
* id: 'user_123',
|
|
131
|
+
* email: 'john@example.com',
|
|
132
|
+
* name: 'John Doe',
|
|
133
|
+
* plan: 'pro',
|
|
134
|
+
* company: 'Acme Inc'
|
|
135
|
+
* })
|
|
136
|
+
*/
|
|
137
|
+
interface UserIdentity {
|
|
138
|
+
/** Required unique user identifier */
|
|
139
|
+
id: string;
|
|
140
|
+
/** User's email address */
|
|
141
|
+
email?: string;
|
|
142
|
+
/** User's display name */
|
|
143
|
+
name?: string;
|
|
144
|
+
/** Any custom fields (plan, company, etc.) */
|
|
145
|
+
[key: string]: unknown;
|
|
146
|
+
}
|
|
147
|
+
type ResolvedPocketPingConfig = Omit<PocketPingConfig, 'endpoint'> & {
|
|
148
|
+
endpoint: string;
|
|
149
|
+
};
|
|
92
150
|
|
|
93
151
|
type Listener<T> = (data: T) => void;
|
|
94
152
|
declare class PocketPingClient {
|
|
@@ -97,10 +155,11 @@ declare class PocketPingClient {
|
|
|
97
155
|
private ws;
|
|
98
156
|
private isOpen;
|
|
99
157
|
private listeners;
|
|
158
|
+
private customEventHandlers;
|
|
100
159
|
private reconnectAttempts;
|
|
101
160
|
private maxReconnectAttempts;
|
|
102
161
|
private reconnectTimeout;
|
|
103
|
-
constructor(config:
|
|
162
|
+
constructor(config: ResolvedPocketPingConfig);
|
|
104
163
|
connect(): Promise<Session>;
|
|
105
164
|
disconnect(): void;
|
|
106
165
|
sendMessage(content: string): Promise<Message>;
|
|
@@ -108,6 +167,33 @@ declare class PocketPingClient {
|
|
|
108
167
|
sendTyping(isTyping?: boolean): Promise<void>;
|
|
109
168
|
sendReadStatus(messageIds: string[], status: MessageStatus): Promise<void>;
|
|
110
169
|
getPresence(): Promise<PresenceResponse>;
|
|
170
|
+
/**
|
|
171
|
+
* Identify the current user with metadata
|
|
172
|
+
* Call after user logs in or when user data becomes available
|
|
173
|
+
* @param identity - User identity data with required id field
|
|
174
|
+
* @example
|
|
175
|
+
* PocketPing.identify({
|
|
176
|
+
* id: 'user_123',
|
|
177
|
+
* email: 'john@example.com',
|
|
178
|
+
* name: 'John Doe',
|
|
179
|
+
* plan: 'pro',
|
|
180
|
+
* company: 'Acme Inc'
|
|
181
|
+
* })
|
|
182
|
+
*/
|
|
183
|
+
identify(identity: UserIdentity): Promise<void>;
|
|
184
|
+
/**
|
|
185
|
+
* Reset the user identity and optionally start a new session
|
|
186
|
+
* Call on user logout to clear user data
|
|
187
|
+
* @param options - Optional settings: { newSession: boolean }
|
|
188
|
+
*/
|
|
189
|
+
reset(options?: {
|
|
190
|
+
newSession?: boolean;
|
|
191
|
+
}): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Get the current user identity
|
|
194
|
+
* @returns UserIdentity or null if not identified
|
|
195
|
+
*/
|
|
196
|
+
getIdentity(): UserIdentity | null;
|
|
111
197
|
getSession(): Session | null;
|
|
112
198
|
getMessages(): Message[];
|
|
113
199
|
isConnected(): boolean;
|
|
@@ -116,14 +202,45 @@ declare class PocketPingClient {
|
|
|
116
202
|
toggleOpen(): void;
|
|
117
203
|
on<T>(event: string, listener: Listener<T>): () => void;
|
|
118
204
|
private emit;
|
|
205
|
+
/**
|
|
206
|
+
* Trigger a custom event to the backend
|
|
207
|
+
* @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
|
|
208
|
+
* @param data - Optional payload to send with the event
|
|
209
|
+
* @example
|
|
210
|
+
* PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
|
|
211
|
+
*/
|
|
212
|
+
trigger(eventName: string, data?: Record<string, unknown>): void;
|
|
213
|
+
/**
|
|
214
|
+
* Subscribe to custom events from the backend
|
|
215
|
+
* @param eventName - The name of the event to listen for (e.g., 'show_offer', 'open_chat')
|
|
216
|
+
* @param handler - Callback function when event is received
|
|
217
|
+
* @returns Unsubscribe function
|
|
218
|
+
* @example
|
|
219
|
+
* const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
|
|
220
|
+
* showPopup(data.message)
|
|
221
|
+
* })
|
|
222
|
+
*/
|
|
223
|
+
onEvent(eventName: string, handler: CustomEventHandler): () => void;
|
|
224
|
+
/**
|
|
225
|
+
* Unsubscribe from a custom event
|
|
226
|
+
* @param eventName - The name of the event
|
|
227
|
+
* @param handler - The handler to remove
|
|
228
|
+
*/
|
|
229
|
+
offEvent(eventName: string, handler: CustomEventHandler): void;
|
|
230
|
+
private emitCustomEvent;
|
|
119
231
|
private connectWebSocket;
|
|
120
232
|
private handleWebSocketEvent;
|
|
233
|
+
private handleVersionWarning;
|
|
121
234
|
private scheduleReconnect;
|
|
122
235
|
private startPolling;
|
|
123
236
|
private fetch;
|
|
237
|
+
private checkVersionHeaders;
|
|
124
238
|
private getOrCreateVisitorId;
|
|
125
239
|
private getStoredSessionId;
|
|
126
240
|
private storeSessionId;
|
|
241
|
+
private getStoredIdentity;
|
|
242
|
+
private storeIdentity;
|
|
243
|
+
private clearIdentity;
|
|
127
244
|
private generateId;
|
|
128
245
|
}
|
|
129
246
|
|
|
@@ -133,6 +250,77 @@ declare function open(): void;
|
|
|
133
250
|
declare function close(): void;
|
|
134
251
|
declare function toggle(): void;
|
|
135
252
|
declare function sendMessage(content: string): Promise<Message>;
|
|
253
|
+
/**
|
|
254
|
+
* Trigger a custom event to the backend
|
|
255
|
+
* @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
|
|
256
|
+
* @param data - Optional payload to send with the event
|
|
257
|
+
* @example
|
|
258
|
+
* PocketPing.trigger('clicked_cta', { button: 'signup', page: '/pricing' })
|
|
259
|
+
*/
|
|
260
|
+
declare function trigger(eventName: string, data?: Record<string, unknown>): void;
|
|
261
|
+
/**
|
|
262
|
+
* Subscribe to custom events from the backend
|
|
263
|
+
* @param eventName - The name of the event to listen for
|
|
264
|
+
* @param handler - Callback function when event is received
|
|
265
|
+
* @returns Unsubscribe function
|
|
266
|
+
* @example
|
|
267
|
+
* const unsubscribe = PocketPing.onEvent('show_offer', (data) => {
|
|
268
|
+
* showPopup(data.message)
|
|
269
|
+
* })
|
|
270
|
+
*/
|
|
271
|
+
declare function onEvent(eventName: string, handler: CustomEventHandler): () => void;
|
|
272
|
+
/**
|
|
273
|
+
* Unsubscribe from a custom event
|
|
274
|
+
* @param eventName - The name of the event
|
|
275
|
+
* @param handler - The handler to remove
|
|
276
|
+
*/
|
|
277
|
+
declare function offEvent(eventName: string, handler: CustomEventHandler): void;
|
|
278
|
+
/**
|
|
279
|
+
* Identify the current user with metadata
|
|
280
|
+
* Call after user logs in or when user data becomes available
|
|
281
|
+
* @param identity - User identity data with required id field
|
|
282
|
+
* @example
|
|
283
|
+
* PocketPing.identify({
|
|
284
|
+
* id: 'user_123',
|
|
285
|
+
* email: 'john@example.com',
|
|
286
|
+
* name: 'John Doe',
|
|
287
|
+
* plan: 'pro',
|
|
288
|
+
* company: 'Acme Inc'
|
|
289
|
+
* })
|
|
290
|
+
*/
|
|
291
|
+
declare function identify(identity: UserIdentity): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Reset the user identity and optionally start a new session
|
|
294
|
+
* Call on user logout to clear user data
|
|
295
|
+
* @param options - Optional settings: { newSession: boolean }
|
|
296
|
+
* @example
|
|
297
|
+
* // Clear identity but keep session
|
|
298
|
+
* PocketPing.reset()
|
|
299
|
+
*
|
|
300
|
+
* // Clear everything and start fresh
|
|
301
|
+
* PocketPing.reset({ newSession: true })
|
|
302
|
+
*/
|
|
303
|
+
declare function reset(options?: {
|
|
304
|
+
newSession?: boolean;
|
|
305
|
+
}): Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* Get the current user identity
|
|
308
|
+
* @returns UserIdentity or null if not identified
|
|
309
|
+
*/
|
|
310
|
+
declare function getIdentity(): UserIdentity | null;
|
|
311
|
+
/**
|
|
312
|
+
* Subscribe to internal widget events
|
|
313
|
+
* @param eventName - Event name: 'versionWarning', 'message', 'connect', 'typing', etc.
|
|
314
|
+
* @param handler - Callback function
|
|
315
|
+
* @returns Unsubscribe function
|
|
316
|
+
* @example
|
|
317
|
+
* PocketPing.on('versionWarning', (warning) => {
|
|
318
|
+
* if (warning.severity === 'error') {
|
|
319
|
+
* showUpgradeNotice(warning.message);
|
|
320
|
+
* }
|
|
321
|
+
* })
|
|
322
|
+
*/
|
|
323
|
+
declare function on<T>(eventName: string, handler: (data: T) => void): () => void;
|
|
136
324
|
declare const _default: {
|
|
137
325
|
init: typeof init;
|
|
138
326
|
destroy: typeof destroy;
|
|
@@ -140,6 +328,13 @@ declare const _default: {
|
|
|
140
328
|
close: typeof close;
|
|
141
329
|
toggle: typeof toggle;
|
|
142
330
|
sendMessage: typeof sendMessage;
|
|
331
|
+
trigger: typeof trigger;
|
|
332
|
+
onEvent: typeof onEvent;
|
|
333
|
+
offEvent: typeof offEvent;
|
|
334
|
+
on: typeof on;
|
|
335
|
+
identify: typeof identify;
|
|
336
|
+
reset: typeof reset;
|
|
337
|
+
getIdentity: typeof getIdentity;
|
|
143
338
|
};
|
|
144
339
|
|
|
145
|
-
export { type Message, type PocketPingConfig, close, _default as default, destroy, init, open, sendMessage, toggle };
|
|
340
|
+
export { type CustomEvent, type CustomEventHandler, type Message, type PocketPingConfig, type UserIdentity, type VersionWarning, close, _default as default, destroy, getIdentity, identify, init, offEvent, on, onEvent, open, reset, sendMessage, toggle, trigger };
|