@v-tilt/browser 1.4.2 → 1.4.4
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/dist/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/array.no-external.js +1 -1
- package/dist/array.no-external.js.map +1 -1
- package/dist/chat.js +1 -1
- package/dist/chat.js.map +1 -1
- package/dist/extensions/chat/chat-wrapper.d.ts +1 -1
- package/dist/extensions/chat/chat.d.ts +3 -33
- package/dist/external-scripts-loader.js +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/dist/module.no-external.js +1 -1
- package/dist/module.no-external.js.map +1 -1
- package/dist/storage.d.ts +68 -51
- package/dist/user-manager.d.ts +15 -1
- package/lib/entrypoints/external-scripts-loader.js +1 -1
- package/lib/extensions/chat/chat-wrapper.d.ts +1 -1
- package/lib/extensions/chat/chat-wrapper.js +12 -6
- package/lib/extensions/chat/chat.d.ts +3 -33
- package/lib/extensions/chat/chat.js +102 -229
- package/lib/storage.d.ts +68 -51
- package/lib/storage.js +306 -219
- package/lib/user-manager.d.ts +15 -1
- package/lib/user-manager.js +38 -6
- package/lib/vtilt.js +6 -2
- package/package.json +1 -1
package/dist/storage.d.ts
CHANGED
|
@@ -1,23 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Unified Storage Manager
|
|
2
|
+
* Unified Storage Manager
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Handles all storage operations for sessions and users with consistent
|
|
5
|
+
* cookie handling across different persistence methods.
|
|
6
6
|
*
|
|
7
7
|
* Storage methods:
|
|
8
|
-
* - cookie
|
|
9
|
-
* - localStorage
|
|
10
|
-
* - sessionStorage
|
|
11
|
-
* - localStorage+cookie
|
|
12
|
-
*
|
|
8
|
+
* - `cookie`: Browser cookies with cross-subdomain support
|
|
9
|
+
* - `localStorage`: Persistent local storage
|
|
10
|
+
* - `sessionStorage`: Tab-specific storage (cleared on tab close)
|
|
11
|
+
* - `localStorage+cookie`: Hybrid mode (default) - full data in localStorage,
|
|
12
|
+
* critical identity properties also in cookies for SSR support
|
|
13
|
+
* - `memory`: In-memory only (no persistence)
|
|
14
|
+
*
|
|
15
|
+
* The `localStorage+cookie` mode is designed for traditional server-side
|
|
16
|
+
* rendered websites where each page navigation reloads JavaScript:
|
|
17
|
+
* - Critical properties (anonymous_id, device_id, etc.) are stored in cookies
|
|
18
|
+
* - Cookies ensure identity persists across full page reloads
|
|
19
|
+
* - localStorage provides fast access for SPA-style navigation
|
|
20
|
+
* - Falls back to cookie-only if localStorage is unavailable
|
|
13
21
|
*/
|
|
14
22
|
import { PersistenceMethod } from "./types";
|
|
23
|
+
/**
|
|
24
|
+
* Critical properties persisted to cookies in `localStorage+cookie` mode.
|
|
25
|
+
* These ensure identity survives full page reloads in traditional SSR websites.
|
|
26
|
+
*/
|
|
27
|
+
export declare const COOKIE_PERSISTED_PROPERTIES: readonly ["__vt_anonymous_id", "__vt_device_id", "__vt_distinct_id", "__vt_user_state"];
|
|
28
|
+
/** Session cookie TTL: 30 minutes */
|
|
15
29
|
export declare const SESSION_COOKIE_MAX_AGE = 1800;
|
|
30
|
+
/** User cookie TTL: 1 year */
|
|
16
31
|
export declare const USER_COOKIE_MAX_AGE = 31536000;
|
|
17
32
|
export interface StorageOptions {
|
|
18
33
|
method: PersistenceMethod;
|
|
34
|
+
/** Enable cross-subdomain cookies (auto-detected if not specified) */
|
|
19
35
|
cross_subdomain?: boolean;
|
|
36
|
+
/** Use secure cookies (auto-detected from protocol if not specified) */
|
|
20
37
|
secure?: boolean;
|
|
38
|
+
/** Cookie SameSite attribute */
|
|
21
39
|
sameSite?: "Strict" | "Lax" | "None";
|
|
22
40
|
}
|
|
23
41
|
export interface StorageItem<T = string> {
|
|
@@ -25,13 +43,15 @@ export interface StorageItem<T = string> {
|
|
|
25
43
|
expiry?: number;
|
|
26
44
|
}
|
|
27
45
|
/**
|
|
28
|
-
*
|
|
29
|
-
* Returns false for platforms
|
|
46
|
+
* Check if cross-subdomain cookies should be enabled.
|
|
47
|
+
* Returns false for shared hosting platforms to prevent cookie conflicts.
|
|
30
48
|
*/
|
|
31
49
|
export declare function shouldUseCrossSubdomainCookie(): boolean;
|
|
32
50
|
/**
|
|
33
51
|
* Unified Storage Manager
|
|
52
|
+
*
|
|
34
53
|
* Provides consistent storage operations across all persistence methods
|
|
54
|
+
* with automatic fallbacks and SSR support.
|
|
35
55
|
*/
|
|
36
56
|
export declare class StorageManager {
|
|
37
57
|
private method;
|
|
@@ -39,62 +59,59 @@ export declare class StorageManager {
|
|
|
39
59
|
private secure;
|
|
40
60
|
private sameSite;
|
|
41
61
|
private memoryStorage;
|
|
62
|
+
private _localStorageSupported;
|
|
42
63
|
constructor(options: StorageOptions);
|
|
64
|
+
/** Check if localStorage is available (result is cached) */
|
|
65
|
+
private isLocalStorageSupported;
|
|
66
|
+
/** Check if a key should be persisted to cookies */
|
|
67
|
+
private isCriticalProperty;
|
|
43
68
|
/**
|
|
44
|
-
* Get a value from storage
|
|
69
|
+
* Get a value from storage.
|
|
70
|
+
*
|
|
71
|
+
* For `localStorage+cookie` mode:
|
|
72
|
+
* - Critical properties: read cookie first (for SSR), fall back to localStorage
|
|
73
|
+
* - Non-critical properties: read from localStorage only
|
|
45
74
|
*/
|
|
46
75
|
get(key: string): string | null;
|
|
47
76
|
/**
|
|
48
|
-
* Set a value in storage
|
|
49
|
-
* @param maxAge
|
|
77
|
+
* Set a value in storage.
|
|
78
|
+
* @param maxAge Cookie max age in seconds (only for cookie-based storage)
|
|
79
|
+
*
|
|
80
|
+
* For `localStorage+cookie` mode:
|
|
81
|
+
* - All values stored in localStorage (if available)
|
|
82
|
+
* - Critical properties ALWAYS stored in cookies for SSR support
|
|
50
83
|
*/
|
|
51
84
|
set(key: string, value: string, maxAge?: number): void;
|
|
52
|
-
/**
|
|
53
|
-
* Remove a value from storage
|
|
54
|
-
*/
|
|
85
|
+
/** Remove a value from storage */
|
|
55
86
|
remove(key: string): void;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
87
|
+
private getLocalStoragePlusCookie;
|
|
88
|
+
private setLocalStoragePlusCookie;
|
|
89
|
+
private removeLocalStoragePlusCookie;
|
|
90
|
+
private getLocalStorage;
|
|
91
|
+
private setLocalStorage;
|
|
92
|
+
private removeLocalStorage;
|
|
93
|
+
private readFromSessionStorage;
|
|
94
|
+
private writeToSessionStorage;
|
|
95
|
+
private removeFromSessionStorage;
|
|
96
|
+
private getCookie;
|
|
97
|
+
private setCookie;
|
|
98
|
+
private removeCookie;
|
|
99
|
+
/** Get JSON value with expiry check */
|
|
60
100
|
getWithExpiry<T>(key: string): T | null;
|
|
61
|
-
/**
|
|
62
|
-
* Set JSON value with optional expiry
|
|
63
|
-
* @param ttlMs - Time to live in milliseconds
|
|
64
|
-
*/
|
|
101
|
+
/** Set JSON value with optional TTL */
|
|
65
102
|
setWithExpiry<T>(key: string, value: T, ttlMs?: number): void;
|
|
66
|
-
/**
|
|
67
|
-
* Get JSON value (no expiry check)
|
|
68
|
-
*/
|
|
103
|
+
/** Get parsed JSON value */
|
|
69
104
|
getJSON<T>(key: string): T | null;
|
|
70
|
-
/**
|
|
71
|
-
* Set JSON value
|
|
72
|
-
*/
|
|
105
|
+
/** Set JSON value */
|
|
73
106
|
setJSON<T>(key: string, value: T, maxAge?: number): void;
|
|
74
|
-
|
|
75
|
-
private setCookie;
|
|
76
|
-
private removeCookie;
|
|
77
|
-
private usesLocalStorage;
|
|
78
|
-
private usesSessionStorage;
|
|
79
|
-
/**
|
|
80
|
-
* Check if sessionStorage is available
|
|
81
|
-
*/
|
|
107
|
+
/** Check if sessionStorage is available */
|
|
82
108
|
canUseSessionStorage(): boolean;
|
|
83
|
-
/**
|
|
84
|
-
* Get direct access to sessionStorage (for window_id which always uses sessionStorage)
|
|
85
|
-
*/
|
|
109
|
+
/** Get sessionStorage instance (for window_id which always uses sessionStorage) */
|
|
86
110
|
getSessionStorage(): Storage | null;
|
|
87
|
-
/**
|
|
88
|
-
* Update storage method at runtime
|
|
89
|
-
*/
|
|
111
|
+
/** Update storage method at runtime */
|
|
90
112
|
setMethod(method: PersistenceMethod): void;
|
|
91
|
-
/**
|
|
92
|
-
* Get current storage method
|
|
93
|
-
*/
|
|
113
|
+
/** Get current storage method */
|
|
94
114
|
getMethod(): PersistenceMethod;
|
|
95
115
|
}
|
|
96
|
-
/**
|
|
97
|
-
* Create a shared storage instance
|
|
98
|
-
* Use this for creating storage managers with consistent settings
|
|
99
|
-
*/
|
|
116
|
+
/** Factory function to create a StorageManager with default settings */
|
|
100
117
|
export declare function createStorageManager(method: PersistenceMethod, cross_subdomain?: boolean): StorageManager;
|
package/dist/user-manager.d.ts
CHANGED
|
@@ -94,7 +94,21 @@ export declare class UserManager {
|
|
|
94
94
|
*/
|
|
95
95
|
update_referrer_info(): void;
|
|
96
96
|
/**
|
|
97
|
-
* Load user identity from storage
|
|
97
|
+
* Load user identity from storage.
|
|
98
|
+
*
|
|
99
|
+
* For traditional SSR websites where each page navigation reloads JavaScript,
|
|
100
|
+
* identity MUST be persisted immediately when generated to ensure the same
|
|
101
|
+
* anonymous_id is used across all page loads.
|
|
102
|
+
*
|
|
103
|
+
* Flow:
|
|
104
|
+
* 1. Load from storage (reads cookies first for critical properties in SSR mode)
|
|
105
|
+
* 2. Generate new IDs if not found
|
|
106
|
+
* 3. Immediately persist to storage (saved to both localStorage and cookies)
|
|
107
|
+
*
|
|
108
|
+
* With `localStorage+cookie` persistence (default):
|
|
109
|
+
* - Critical properties are stored in cookies for SSR compatibility
|
|
110
|
+
* - Full data is stored in localStorage for fast SPA-style access
|
|
111
|
+
* - Cookies ensure identity persists across full page reloads
|
|
98
112
|
*/
|
|
99
113
|
private loadUserIdentity;
|
|
100
114
|
/**
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* Code config always takes precedence over dashboard settings.
|
|
32
32
|
*/
|
|
33
33
|
import type { VTilt } from "../../vtilt";
|
|
34
|
-
import type
|
|
34
|
+
import { type ChatConfig, type ChatChannelSummary, type ChatWidgetView } from "../../utils/globals";
|
|
35
35
|
import type { MessageCallback, TypingCallback, ConnectionCallback, Unsubscribe } from "./types";
|
|
36
36
|
/** Status when lazy loading is in progress */
|
|
37
37
|
export declare const CHAT_LOADING: "loading";
|
|
@@ -352,13 +352,16 @@ class ChatWrapper {
|
|
|
352
352
|
get _isChatEnabled() {
|
|
353
353
|
var _a;
|
|
354
354
|
// Code config takes precedence
|
|
355
|
-
if (this._config.enabled === false)
|
|
355
|
+
if (this._config.enabled === false) {
|
|
356
356
|
return false;
|
|
357
|
-
|
|
357
|
+
}
|
|
358
|
+
if (this._config.enabled === true) {
|
|
358
359
|
return true;
|
|
360
|
+
}
|
|
359
361
|
// Fall back to server config
|
|
360
|
-
if (((_a = this._serverConfig) === null || _a === void 0 ? void 0 : _a.enabled) === true)
|
|
362
|
+
if (((_a = this._serverConfig) === null || _a === void 0 ? void 0 : _a.enabled) === true) {
|
|
361
363
|
return true;
|
|
364
|
+
}
|
|
362
365
|
// Default: disabled unless explicitly enabled
|
|
363
366
|
return false;
|
|
364
367
|
}
|
|
@@ -367,8 +370,9 @@ class ChatWrapper {
|
|
|
367
370
|
* This enables "snippet-only" installation where widget configures from dashboard
|
|
368
371
|
*/
|
|
369
372
|
async _fetchServerSettings() {
|
|
370
|
-
if (this._configFetched)
|
|
373
|
+
if (this._configFetched) {
|
|
371
374
|
return;
|
|
375
|
+
}
|
|
372
376
|
const config = this._instance.getConfig();
|
|
373
377
|
const token = config.token;
|
|
374
378
|
const apiHost = config.api_host;
|
|
@@ -399,11 +403,13 @@ class ChatWrapper {
|
|
|
399
403
|
* This creates a lightweight bubble that loads the full widget on click
|
|
400
404
|
*/
|
|
401
405
|
_showBubble() {
|
|
402
|
-
if (!(globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.document))
|
|
406
|
+
if (!(globals_1.window === null || globals_1.window === void 0 ? void 0 : globals_1.window.document)) {
|
|
403
407
|
return;
|
|
408
|
+
}
|
|
404
409
|
// Don't create if already exists
|
|
405
|
-
if (document.getElementById("vtilt-chat-bubble"))
|
|
410
|
+
if (document.getElementById("vtilt-chat-bubble")) {
|
|
406
411
|
return;
|
|
412
|
+
}
|
|
407
413
|
const mergedConfig = this.getMergedConfig();
|
|
408
414
|
const position = mergedConfig.position || "bottom-right";
|
|
409
415
|
const color = mergedConfig.color || "#6366f1";
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lazy
|
|
3
|
-
*
|
|
4
|
-
* The actual chat widget implementation that is loaded on demand.
|
|
5
|
-
* This file is bundled into chat.js and loaded when chat is enabled.
|
|
6
|
-
*
|
|
7
|
-
* Uses Ably for real-time messaging.
|
|
2
|
+
* Chat Widget - Lazy loaded chat implementation using Ably for real-time messaging.
|
|
8
3
|
*/
|
|
9
4
|
import type { VTilt } from "../../vtilt";
|
|
10
|
-
import type
|
|
11
|
-
import type
|
|
5
|
+
import { type ChatConfig, type ChatChannel, type ChatChannelSummary, type ChatWidgetView, type LazyLoadedChatInterface } from "../../utils/globals";
|
|
6
|
+
import { type MessageCallback, type TypingCallback, type ConnectionCallback, type Unsubscribe } from "./types";
|
|
12
7
|
export declare class LazyLoadedChat implements LazyLoadedChatInterface {
|
|
13
8
|
private _instance;
|
|
14
9
|
private _config;
|
|
@@ -23,7 +18,6 @@ export declare class LazyLoadedChat implements LazyLoadedChatInterface {
|
|
|
23
18
|
private _messageCallbacks;
|
|
24
19
|
private _typingCallbacks;
|
|
25
20
|
private _connectionCallbacks;
|
|
26
|
-
private _typingTimeout;
|
|
27
21
|
private _typingDebounce;
|
|
28
22
|
private _isUserTyping;
|
|
29
23
|
private _initialUserReadAt;
|
|
@@ -43,32 +37,13 @@ export declare class LazyLoadedChat implements LazyLoadedChatInterface {
|
|
|
43
37
|
toggle(): void;
|
|
44
38
|
show(): void;
|
|
45
39
|
hide(): void;
|
|
46
|
-
/**
|
|
47
|
-
* Fetch/refresh the list of user's channels
|
|
48
|
-
*/
|
|
49
40
|
getChannels(): Promise<void>;
|
|
50
|
-
/**
|
|
51
|
-
* Select a channel and load its messages
|
|
52
|
-
*/
|
|
53
41
|
selectChannel(channelId: string): Promise<void>;
|
|
54
|
-
/**
|
|
55
|
-
* Create a new channel and enter it
|
|
56
|
-
*/
|
|
57
42
|
createChannel(): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* Go back to channel list from conversation view
|
|
60
|
-
*/
|
|
61
43
|
goToChannelList(): void;
|
|
62
44
|
sendMessage(content: string): Promise<void>;
|
|
63
45
|
markAsRead(): void;
|
|
64
|
-
/**
|
|
65
|
-
* Automatically mark unread agent/AI messages as read
|
|
66
|
-
* Called when widget opens or new messages arrive while open
|
|
67
|
-
*/
|
|
68
46
|
private _autoMarkAsRead;
|
|
69
|
-
/**
|
|
70
|
-
* Check if a message has been read by the user (using initial cursor)
|
|
71
|
-
*/
|
|
72
47
|
private _isMessageReadByUser;
|
|
73
48
|
onMessage(callback: MessageCallback): Unsubscribe;
|
|
74
49
|
onTyping(callback: TypingCallback): Unsubscribe;
|
|
@@ -86,7 +61,6 @@ export declare class LazyLoadedChat implements LazyLoadedChatInterface {
|
|
|
86
61
|
private _handleUserTyping;
|
|
87
62
|
private _sendTypingIndicator;
|
|
88
63
|
private _handleSend;
|
|
89
|
-
private _previousView;
|
|
90
64
|
private _updateUI;
|
|
91
65
|
private _updateHeader;
|
|
92
66
|
private _getChannelListHTML;
|
|
@@ -96,16 +70,12 @@ export declare class LazyLoadedChat implements LazyLoadedChatInterface {
|
|
|
96
70
|
private _attachConversationListeners;
|
|
97
71
|
private _formatRelativeTime;
|
|
98
72
|
private _renderMessages;
|
|
99
|
-
private _isMobile;
|
|
100
73
|
private _getContainerStyles;
|
|
101
74
|
private _getBubbleStyles;
|
|
102
75
|
private _getBubbleHTML;
|
|
103
76
|
private _getWidgetStyles;
|
|
104
77
|
private _getWidgetHTML;
|
|
105
78
|
private _getMessageHTML;
|
|
106
|
-
/**
|
|
107
|
-
* Check if a message has been read by the agent using cursor comparison
|
|
108
|
-
*/
|
|
109
79
|
private _isMessageReadByAgent;
|
|
110
80
|
private _apiRequest;
|
|
111
81
|
private _trackEvent;
|