@v-tilt/browser 1.2.0 → 1.4.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 (61) hide show
  1. package/dist/all-external-dependencies.js +2 -0
  2. package/dist/all-external-dependencies.js.map +1 -0
  3. package/dist/array.full.js +2 -0
  4. package/dist/array.full.js.map +1 -0
  5. package/dist/array.js +1 -1
  6. package/dist/array.js.map +1 -1
  7. package/dist/array.no-external.js +1 -1
  8. package/dist/array.no-external.js.map +1 -1
  9. package/dist/chat.js +2 -0
  10. package/dist/chat.js.map +1 -0
  11. package/dist/entrypoints/all-external-dependencies.d.ts +8 -0
  12. package/dist/entrypoints/array.full.d.ts +17 -0
  13. package/dist/entrypoints/chat.d.ts +22 -0
  14. package/dist/entrypoints/web-vitals.d.ts +14 -0
  15. package/dist/extensions/chat/chat-wrapper.d.ts +172 -0
  16. package/dist/extensions/chat/chat.d.ts +87 -0
  17. package/dist/extensions/chat/index.d.ts +10 -0
  18. package/dist/extensions/chat/types.d.ts +156 -0
  19. package/dist/external-scripts-loader.js +1 -1
  20. package/dist/external-scripts-loader.js.map +1 -1
  21. package/dist/main.js +1 -1
  22. package/dist/main.js.map +1 -1
  23. package/dist/module.d.ts +312 -5
  24. package/dist/module.js +1 -1
  25. package/dist/module.js.map +1 -1
  26. package/dist/module.no-external.d.ts +312 -5
  27. package/dist/module.no-external.js +1 -1
  28. package/dist/module.no-external.js.map +1 -1
  29. package/dist/recorder.js.map +1 -1
  30. package/dist/types.d.ts +59 -2
  31. package/dist/utils/globals.d.ts +138 -1
  32. package/dist/vtilt.d.ts +11 -1
  33. package/dist/web-vitals.d.ts +89 -5
  34. package/dist/web-vitals.js +2 -0
  35. package/dist/web-vitals.js.map +1 -0
  36. package/lib/config.js +5 -3
  37. package/lib/entrypoints/all-external-dependencies.d.ts +8 -0
  38. package/lib/entrypoints/all-external-dependencies.js +10 -0
  39. package/lib/entrypoints/array.full.d.ts +17 -0
  40. package/lib/entrypoints/array.full.js +19 -0
  41. package/lib/entrypoints/chat.d.ts +22 -0
  42. package/lib/entrypoints/chat.js +32 -0
  43. package/lib/entrypoints/external-scripts-loader.js +1 -1
  44. package/lib/entrypoints/web-vitals.d.ts +14 -0
  45. package/lib/entrypoints/web-vitals.js +29 -0
  46. package/lib/extensions/chat/chat-wrapper.d.ts +172 -0
  47. package/lib/extensions/chat/chat-wrapper.js +497 -0
  48. package/lib/extensions/chat/chat.d.ts +87 -0
  49. package/lib/extensions/chat/chat.js +998 -0
  50. package/lib/extensions/chat/index.d.ts +10 -0
  51. package/lib/extensions/chat/index.js +27 -0
  52. package/lib/extensions/chat/types.d.ts +156 -0
  53. package/lib/extensions/chat/types.js +22 -0
  54. package/lib/types.d.ts +59 -2
  55. package/lib/types.js +16 -0
  56. package/lib/utils/globals.d.ts +138 -1
  57. package/lib/vtilt.d.ts +11 -1
  58. package/lib/vtilt.js +42 -1
  59. package/lib/web-vitals.d.ts +89 -5
  60. package/lib/web-vitals.js +354 -46
  61. package/package.json +66 -65
@@ -59,8 +59,11 @@ interface VTiltConfig {
59
59
  person_profiles?: PersonProfilesMode;
60
60
  /** Enable autocapture */
61
61
  autocapture?: boolean;
62
- /** Enable web vitals tracking */
63
- capture_performance?: boolean;
62
+ /**
63
+ * Enable web vitals tracking.
64
+ * Can be a boolean or an object with detailed configuration.
65
+ */
66
+ capture_performance?: boolean | CapturePerformanceConfig;
64
67
  /** Enable page view tracking */
65
68
  capture_pageview?: boolean | "auto";
66
69
  /** Enable page leave tracking */
@@ -83,6 +86,10 @@ interface VTiltConfig {
83
86
  session_recording?: SessionRecordingOptions;
84
87
  /** Disable session recording (convenience flag) */
85
88
  disable_session_recording?: boolean;
89
+ /** Chat widget configuration */
90
+ chat?: ChatWidgetConfig;
91
+ /** Disable chat (convenience flag) */
92
+ disable_chat?: boolean;
86
93
  /** Global attributes added to all events */
87
94
  globalAttributes?: Record<string, string>;
88
95
  /** Bootstrap data for initialization */
@@ -168,6 +175,29 @@ interface AliasEvent {
168
175
  distinct_id: string;
169
176
  original: string;
170
177
  }
178
+ /** Supported Web Vitals metrics */
179
+ type SupportedWebVitalsMetric = "LCP" | "CLS" | "FCP" | "INP" | "TTFB";
180
+ /** All supported Web Vitals metrics */
181
+ declare const ALL_WEB_VITALS_METRICS: SupportedWebVitalsMetric[];
182
+ /** Default Web Vitals metrics (matches PostHog defaults) */
183
+ declare const DEFAULT_WEB_VITALS_METRICS: SupportedWebVitalsMetric[];
184
+ /**
185
+ * Web Vitals capture configuration
186
+ */
187
+ interface CapturePerformanceConfig {
188
+ /** Enable or disable web vitals capture */
189
+ web_vitals?: boolean;
190
+ /** Which metrics to capture (default: LCP, CLS, FCP, INP) */
191
+ web_vitals_allowed_metrics?: SupportedWebVitalsMetric[];
192
+ /** Delay before flushing metrics in ms (default: 5000) */
193
+ web_vitals_delayed_flush_ms?: number;
194
+ /**
195
+ * Maximum allowed metric value in ms (default: 900000 = 15 minutes)
196
+ * Values above this are considered anomalies and ignored.
197
+ * Set to 0 to disable this check.
198
+ */
199
+ __web_vitals_max_value?: number;
200
+ }
171
201
  interface WebVitalMetric {
172
202
  name: string;
173
203
  value: number;
@@ -175,6 +205,10 @@ interface WebVitalMetric {
175
205
  rating: "good" | "needs-improvement" | "poor";
176
206
  id: string;
177
207
  navigationType: string;
208
+ /** Timestamp when the metric was captured (added internally) */
209
+ timestamp?: number;
210
+ /** Attribution data from web-vitals library */
211
+ attribution?: Record<string, unknown>;
178
212
  }
179
213
  interface GeolocationData {
180
214
  country?: string;
@@ -267,6 +301,29 @@ interface SessionRecordingOptions {
267
301
  /** Internal: Mutation throttler bucket size */
268
302
  __mutationThrottlerBucketSize?: number;
269
303
  }
304
+ /** Chat widget configuration */
305
+ interface ChatWidgetConfig {
306
+ /** Enable/disable chat widget (default: auto from dashboard) */
307
+ enabled?: boolean;
308
+ /** Auto-fetch settings from dashboard (default: true) */
309
+ autoConfig?: boolean;
310
+ /** Widget position (default: 'bottom-right') */
311
+ position?: "bottom-right" | "bottom-left";
312
+ /** Widget header/greeting message */
313
+ greeting?: string;
314
+ /** Widget primary color */
315
+ color?: string;
316
+ /** Start in AI mode (default: true) */
317
+ aiMode?: boolean;
318
+ /** AI greeting message (first message from AI) */
319
+ aiGreeting?: string;
320
+ /** Preload widget script on idle vs on-demand */
321
+ preload?: boolean;
322
+ /** Offline message shown when business is unavailable */
323
+ offlineMessage?: string;
324
+ /** Collect email when offline */
325
+ collectEmailOffline?: boolean;
326
+ }
270
327
  interface RemoteConfig {
271
328
  /** Default to identified_only mode */
272
329
  defaultIdentifiedOnly?: boolean;
@@ -377,6 +434,94 @@ interface SessionRecordingConfig {
377
434
  /** Recording start reason */
378
435
  type SessionStartReason = "recording_initialized" | "session_id_changed" | "linked_flag_matched" | "linked_flag_overridden" | "sampling_overridden" | "url_trigger_matched" | "event_trigger_matched" | "sampled";
379
436
 
437
+ /**
438
+ * Chat message structure (matches PostgreSQL chat_messages table)
439
+ * Note: Read status is determined by cursor comparison, not per-message
440
+ */
441
+ interface ChatMessage {
442
+ id: string;
443
+ channel_id: string;
444
+ sender_type: "user" | "agent" | "ai" | "system";
445
+ sender_id: string | null;
446
+ sender_name: string | null;
447
+ sender_avatar_url: string | null;
448
+ content: string;
449
+ content_type: "text" | "html" | "attachment";
450
+ metadata: Record<string, unknown>;
451
+ created_at: string;
452
+ }
453
+ /**
454
+ * Chat channel structure (maps 1:1 to Ably channel)
455
+ */
456
+ interface ChatChannel {
457
+ id: string;
458
+ project_id: string;
459
+ person_id: string;
460
+ distinct_id: string;
461
+ status: "open" | "closed" | "snoozed";
462
+ ai_mode: boolean;
463
+ unread_count: number;
464
+ last_message_at: string | null;
465
+ last_message_preview: string | null;
466
+ last_message_sender: "user" | "agent" | "ai" | "system" | null;
467
+ user_last_read_at: string | null;
468
+ agent_last_read_at: string | null;
469
+ created_at: string;
470
+ }
471
+ /**
472
+ * Chat widget configuration
473
+ *
474
+ * Settings can come from two sources:
475
+ * 1. Dashboard (fetched from /api/chat/settings) - "snippet-only" mode
476
+ * 2. Code config (passed to vt.init) - overrides dashboard settings
477
+ *
478
+ * This enables Intercom-like flexibility: just add snippet OR customize with code.
479
+ */
480
+ interface ChatConfig {
481
+ /**
482
+ * Enable/disable chat widget.
483
+ * - undefined: Use dashboard setting (auto-fetch)
484
+ * - true: Enable (override dashboard)
485
+ * - false: Disable entirely
486
+ */
487
+ enabled?: boolean;
488
+ /**
489
+ * Auto-fetch settings from dashboard (default: true)
490
+ * When true, SDK fetches /api/chat/settings and uses those as base config.
491
+ * Code config always overrides fetched settings.
492
+ */
493
+ autoConfig?: boolean;
494
+ /** Widget position (default: 'bottom-right') */
495
+ position?: "bottom-right" | "bottom-left";
496
+ /** Widget header/greeting message */
497
+ greeting?: string;
498
+ /** Widget primary color */
499
+ color?: string;
500
+ /** Start in AI mode (default: true) */
501
+ aiMode?: boolean;
502
+ /** AI greeting message (first message from AI) */
503
+ aiGreeting?: string;
504
+ /** Preload widget script on idle vs on-demand */
505
+ preload?: boolean;
506
+ /** Custom theme */
507
+ theme?: ChatTheme;
508
+ /** Offline message shown when business is unavailable */
509
+ offlineMessage?: string;
510
+ /** Collect email when offline */
511
+ collectEmailOffline?: boolean;
512
+ }
513
+ /**
514
+ * Chat theme customization
515
+ */
516
+ interface ChatTheme {
517
+ primaryColor?: string;
518
+ fontFamily?: string;
519
+ borderRadius?: string;
520
+ headerBgColor?: string;
521
+ userBubbleColor?: string;
522
+ agentBubbleColor?: string;
523
+ }
524
+
380
525
  /**
381
526
  * Session Recording Wrapper
382
527
  *
@@ -437,6 +582,159 @@ declare class SessionRecordingWrapper {
437
582
  private _onScriptLoaded;
438
583
  }
439
584
 
585
+ /**
586
+ * Message callback type
587
+ */
588
+ type MessageCallback = (message: ChatMessage) => void;
589
+ /**
590
+ * Typing callback type
591
+ */
592
+ type TypingCallback = (isTyping: boolean, senderType: string) => void;
593
+ /**
594
+ * Connection callback type
595
+ */
596
+ type ConnectionCallback = (connected: boolean) => void;
597
+ /**
598
+ * Unsubscribe function type
599
+ */
600
+ type Unsubscribe = () => void;
601
+
602
+ /**
603
+ * Chat Wrapper
604
+ *
605
+ * This is the lightweight class that lives in the main bundle.
606
+ * It handles:
607
+ * - Auto-fetching settings from dashboard (Intercom-like)
608
+ * - Merging server settings with code config
609
+ * - Deciding if chat should be enabled
610
+ * - Lazy loading the actual chat widget code
611
+ * - Delegating to LazyLoadedChat
612
+ * - Queuing messages/callbacks before widget loads
613
+ */
614
+ declare class ChatWrapper {
615
+ private readonly _instance;
616
+ private _lazyLoadedChat;
617
+ private _config;
618
+ private _serverConfig;
619
+ private _configFetched;
620
+ private _isLoading;
621
+ private _loadError;
622
+ private _pendingMessages;
623
+ private _pendingCallbacks;
624
+ private _messageCallbacks;
625
+ private _typingCallbacks;
626
+ private _connectionCallbacks;
627
+ constructor(_instance: VTilt, config?: ChatConfig);
628
+ /**
629
+ * Whether the chat widget is open
630
+ */
631
+ get isOpen(): boolean;
632
+ /**
633
+ * Whether connected to realtime service
634
+ */
635
+ get isConnected(): boolean;
636
+ /**
637
+ * Whether the widget is loading
638
+ */
639
+ get isLoading(): boolean;
640
+ /**
641
+ * Number of unread messages
642
+ */
643
+ get unreadCount(): number;
644
+ /**
645
+ * Current channel (if any)
646
+ */
647
+ get channel(): ChatChannel | null;
648
+ /**
649
+ * Open the chat widget
650
+ */
651
+ open(): void;
652
+ /**
653
+ * Close the chat widget
654
+ */
655
+ close(): void;
656
+ /**
657
+ * Toggle the chat widget open/closed
658
+ */
659
+ toggle(): void;
660
+ /**
661
+ * Show the chat widget (make visible but not necessarily open)
662
+ */
663
+ show(): void;
664
+ /**
665
+ * Hide the chat widget
666
+ */
667
+ hide(): void;
668
+ /**
669
+ * Send a message
670
+ */
671
+ sendMessage(content: string): void;
672
+ /**
673
+ * Mark messages as read
674
+ */
675
+ markAsRead(): void;
676
+ /**
677
+ * Subscribe to new messages
678
+ */
679
+ onMessage(callback: MessageCallback): Unsubscribe;
680
+ /**
681
+ * Subscribe to typing indicators
682
+ */
683
+ onTyping(callback: TypingCallback): Unsubscribe;
684
+ /**
685
+ * Subscribe to connection changes
686
+ */
687
+ onConnectionChange(callback: ConnectionCallback): Unsubscribe;
688
+ /**
689
+ * Start chat if enabled, called by VTilt after init
690
+ *
691
+ * This method supports two modes (Intercom-like):
692
+ * 1. Auto-config: Fetch settings from /api/chat/settings (default)
693
+ * 2. Code-only: Use only code config (autoConfig: false)
694
+ */
695
+ startIfEnabled(): Promise<void>;
696
+ /**
697
+ * Update configuration
698
+ */
699
+ updateConfig(config: Partial<ChatConfig>): void;
700
+ /**
701
+ * Get the merged configuration (server + code, code takes precedence)
702
+ */
703
+ getMergedConfig(): ChatConfig;
704
+ /**
705
+ * Destroy the chat widget
706
+ */
707
+ destroy(): void;
708
+ private get _isChatEnabled();
709
+ /**
710
+ * Fetch chat settings from the server
711
+ * This enables "snippet-only" installation where widget configures from dashboard
712
+ */
713
+ private _fetchServerSettings;
714
+ /**
715
+ * Show the chat bubble (launcher button) without fully loading the widget
716
+ * This creates a lightweight bubble that loads the full widget on click
717
+ */
718
+ private _showBubble;
719
+ private get _scriptName();
720
+ /**
721
+ * Schedule preload on idle
722
+ */
723
+ private _schedulePreload;
724
+ /**
725
+ * Lazy load and then execute callback
726
+ */
727
+ private _lazyLoadAndThen;
728
+ /**
729
+ * Lazy load the chat script
730
+ */
731
+ private _lazyLoad;
732
+ /**
733
+ * Called after the chat script is loaded
734
+ */
735
+ private _onScriptLoaded;
736
+ }
737
+
440
738
  /**
441
739
  * Request Queue - Event Batching (PostHog-style)
442
740
  *
@@ -468,6 +766,7 @@ declare class VTilt {
468
766
  private rateLimiter;
469
767
  historyAutocapture?: HistoryAutocapture;
470
768
  sessionRecording?: SessionRecordingWrapper;
769
+ chat?: ChatWrapper;
471
770
  __loaded: boolean;
472
771
  private _initial_pageview_captured;
473
772
  private _visibility_state_listener;
@@ -726,11 +1025,19 @@ declare class VTilt {
726
1025
  /**
727
1026
  * Check if session recording is active
728
1027
  */
729
- isSessionRecordingActive(): boolean;
1028
+ isRecordingActive(): boolean;
730
1029
  /**
731
1030
  * Get session recording ID
732
1031
  */
733
1032
  getSessionRecordingId(): string | null;
1033
+ /**
1034
+ * Initialize chat widget
1035
+ */
1036
+ private _initChat;
1037
+ /**
1038
+ * Build chat config from VTiltConfig
1039
+ */
1040
+ private _buildChatConfig;
734
1041
  /**
735
1042
  * _execute_array() deals with processing any vTilt function
736
1043
  * calls that were called before the vTilt library was loaded
@@ -752,5 +1059,5 @@ declare class VTilt {
752
1059
 
753
1060
  declare const vt: VTilt;
754
1061
 
755
- export { VTilt, vt as default, vt };
756
- export type { AliasEvent, CaptureOptions, CaptureResult, EventPayload, FeatureFlagsConfig, GeolocationData, GroupsConfig, PersistenceMethod, Properties, Property, PropertyOperations, RemoteConfig, RequestOptions, SessionData, SessionIdChangedCallback, SessionRecordingMaskInputOptions, SessionRecordingOptions, TrackingEvent, UserIdentity, UserProperties, VTiltConfig, WebVitalMetric };
1062
+ export { ALL_WEB_VITALS_METRICS, DEFAULT_WEB_VITALS_METRICS, VTilt, vt as default, vt };
1063
+ export type { AliasEvent, CaptureOptions, CapturePerformanceConfig, CaptureResult, ChatWidgetConfig, EventPayload, FeatureFlagsConfig, GeolocationData, GroupsConfig, PersistenceMethod, Properties, Property, PropertyOperations, RemoteConfig, RequestOptions, SessionData, SessionIdChangedCallback, SessionRecordingMaskInputOptions, SessionRecordingOptions, SupportedWebVitalsMetric, TrackingEvent, UserIdentity, UserProperties, VTiltConfig, WebVitalMetric };