@prosdevlab/experience-sdk-plugins 0.1.4 → 0.2.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @prosdevlab/experience-sdk-plugins@0.1.4 build /home/runner/work/experience-sdk/experience-sdk/packages/plugins
2
+ > @prosdevlab/experience-sdk-plugins@0.2.0 build /home/runner/work/experience-sdk/experience-sdk/packages/plugins
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -9,9 +9,9 @@
9
9
  CLI Target: es2024
10
10
  CLI Cleaning output folder
11
11
  ESM Build start
12
- ESM dist/index.js 19.53 KB
13
- ESM dist/index.js.map 48.09 KB
14
- ESM ⚡️ Build success in 140ms
12
+ ESM dist/index.js 40.31 KB
13
+ ESM dist/index.js.map 105.77 KB
14
+ ESM ⚡️ Build success in 262ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 857ms
17
- DTS dist/index.d.ts 5.46 KB
16
+ DTS ⚡️ Build success in 1098ms
17
+ DTS dist/index.d.ts 22.78 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @prosdevlab/experience-sdk-plugins
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 02de640: feat: add display condition plugins with event-driven architecture
8
+
9
+ Add 4 new display condition plugins with comprehensive testing and documentation:
10
+
11
+ **New Plugins:**
12
+
13
+ - Exit Intent: Velocity-based mouse tracking with session awareness
14
+ - Scroll Depth: Multiple thresholds with advanced engagement metrics
15
+ - Page Visits: Session and lifetime counters with first-visit detection
16
+ - Time Delay: Millisecond-precision delays with visibility API integration
17
+
18
+ **Core Enhancements:**
19
+
20
+ - Event-driven trigger architecture (`trigger:*` events)
21
+ - Composable display conditions (AND/OR/NOT logic)
22
+ - TriggerState interface for type-safe context updates
23
+
24
+ **Developer Experience:**
25
+
26
+ - 101 new tests across 4 plugins (314 total)
27
+ - 12 integration tests for plugin composition
28
+ - Complete API documentation with examples
29
+ - Pure functions for easier testing
30
+
31
+ All plugins are backward compatible and work independently or together.
32
+
3
33
  ## 0.1.4
4
34
 
5
35
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -192,6 +192,140 @@ interface DebugPlugin {
192
192
  */
193
193
  declare const debugPlugin: PluginFunction;
194
194
 
195
+ /**
196
+ * Exit Intent Plugin Configuration
197
+ */
198
+ interface ExitIntentPluginConfig {
199
+ exitIntent?: {
200
+ /**
201
+ * Maximum Y position (px) where exit intent can trigger
202
+ * @default 50
203
+ */
204
+ sensitivity?: number;
205
+ /**
206
+ * Minimum time on page (ms) before exit intent is active
207
+ * Prevents immediate triggers on page load
208
+ * @default 2000
209
+ */
210
+ minTimeOnPage?: number;
211
+ /**
212
+ * Delay (ms) between detection and trigger
213
+ * @default 0
214
+ */
215
+ delay?: number;
216
+ /**
217
+ * Number of mouse positions to track for velocity calculation
218
+ * @default 30
219
+ */
220
+ positionHistorySize?: number;
221
+ /**
222
+ * Disable exit intent on mobile devices
223
+ * @default true
224
+ */
225
+ disableOnMobile?: boolean;
226
+ };
227
+ }
228
+ /**
229
+ * Exit Intent Event Payload
230
+ */
231
+ interface ExitIntentEvent {
232
+ timestamp: number;
233
+ lastY: number;
234
+ previousY: number;
235
+ velocity: number;
236
+ timeOnPage: number;
237
+ }
238
+ /**
239
+ * Exit Intent Plugin API
240
+ */
241
+ interface ExitIntentPlugin {
242
+ isTriggered(): boolean;
243
+ reset(): void;
244
+ getPositions(): Array<{
245
+ x: number;
246
+ y: number;
247
+ }>;
248
+ }
249
+
250
+ /**
251
+ * Exit Intent Plugin
252
+ *
253
+ * Detects when users are about to leave the page by tracking upward mouse movement
254
+ * near the top of the viewport. Inspired by Pathfora's showOnExitIntent.
255
+ *
256
+ * **Event-Driven Architecture:**
257
+ * This plugin emits `trigger:exitIntent` events when exit intent is detected.
258
+ * The core runtime listens for these events and automatically re-evaluates experiences.
259
+ *
260
+ * **Usage Pattern:**
261
+ * Use `targeting.custom` to check if exit intent has triggered:
262
+ *
263
+ * @example Basic usage
264
+ * ```typescript
265
+ * import { init, register } from '@prosdevlab/experience-sdk';
266
+ * import { exitIntentPlugin } from '@prosdevlab/experience-sdk-plugins';
267
+ *
268
+ * init({
269
+ * plugins: [exitIntentPlugin],
270
+ * exitIntent: {
271
+ * sensitivity: 20, // Trigger within 20px of top (default: 50)
272
+ * minTimeOnPage: 2000, // Wait 2s before enabling (default: 2000)
273
+ * delay: 0, // Delay after trigger (default: 0)
274
+ * disableOnMobile: true // Disable on mobile (default: true)
275
+ * }
276
+ * });
277
+ *
278
+ * // Show banner only when exit intent is detected
279
+ * register('exit-offer', {
280
+ * type: 'banner',
281
+ * content: {
282
+ * title: 'Wait! Don't leave yet!',
283
+ * message: 'Get 15% off your first order',
284
+ * buttons: [{ text: 'Claim Offer', variant: 'primary' }]
285
+ * },
286
+ * targeting: {
287
+ * custom: (context) => context.triggers?.exitIntent?.triggered === true
288
+ * },
289
+ * frequency: { max: 1, per: 'session' } // Only show once per session
290
+ * });
291
+ * ```
292
+ *
293
+ * @example Combining with other conditions
294
+ * ```typescript
295
+ * // Show exit offer only on shop pages with items in cart
296
+ * register('cart-recovery', {
297
+ * type: 'banner',
298
+ * content: { message: 'Complete your purchase and save!' },
299
+ * targeting: {
300
+ * url: { contains: '/shop' },
301
+ * custom: (context) => {
302
+ * return (
303
+ * context.triggers?.exitIntent?.triggered === true &&
304
+ * getCart().items.length > 0
305
+ * );
306
+ * }
307
+ * }
308
+ * });
309
+ * ```
310
+ *
311
+ * @example Combining multiple triggers (exit intent + scroll depth)
312
+ * ```typescript
313
+ * // Show offer on exit intent OR after 70% scroll
314
+ * register('engaged-exit', {
315
+ * type: 'banner',
316
+ * content: { message: 'You're almost there!' },
317
+ * targeting: {
318
+ * custom: (context) => {
319
+ * const exitIntent = context.triggers?.exitIntent?.triggered;
320
+ * const scrolled = (context.triggers?.scrollDepth?.percent || 0) >= 70;
321
+ * return exitIntent || scrolled;
322
+ * }
323
+ * }
324
+ * });
325
+ * ```
326
+ */
327
+ declare const exitIntentPlugin: PluginFunction;
328
+
195
329
  /**
196
330
  * Frequency Capping Plugin
197
331
  *
@@ -227,4 +361,477 @@ interface FrequencyPlugin {
227
361
  */
228
362
  declare const frequencyPlugin: PluginFunction;
229
363
 
230
- export { type BannerContent, type BannerPlugin, type BannerPluginConfig, type DebugPlugin, type DebugPluginConfig, type Decision, type DecisionMetadata, type Experience, type ExperienceContent, type FrequencyPlugin, type FrequencyPluginConfig, type ModalContent, type TooltipContent, type TraceStep, bannerPlugin, debugPlugin, frequencyPlugin };
364
+ /**
365
+ * Page Visits Plugin Types
366
+ *
367
+ * Generic page visit tracking for any SDK built on sdk-kit.
368
+ * Tracks session and lifetime visit counts with first-visit detection.
369
+ */
370
+ /**
371
+ * Page visits plugin configuration
372
+ */
373
+ interface PageVisitsPluginConfig {
374
+ pageVisits?: {
375
+ /**
376
+ * Enable/disable page visit tracking
377
+ * @default true
378
+ */
379
+ enabled?: boolean;
380
+ /**
381
+ * Honor Do Not Track browser setting
382
+ * @default true
383
+ */
384
+ respectDNT?: boolean;
385
+ /**
386
+ * Storage key for session count
387
+ * @default 'pageVisits:session'
388
+ */
389
+ sessionKey?: string;
390
+ /**
391
+ * Storage key for lifetime data
392
+ * @default 'pageVisits:total'
393
+ */
394
+ totalKey?: string;
395
+ /**
396
+ * TTL for lifetime data in seconds (GDPR compliance)
397
+ * @default undefined (no expiration)
398
+ */
399
+ ttl?: number;
400
+ /**
401
+ * Automatically increment on plugin load
402
+ * @default true
403
+ */
404
+ autoIncrement?: boolean;
405
+ };
406
+ }
407
+ /**
408
+ * Page visits event payload
409
+ */
410
+ interface PageVisitsEvent {
411
+ /** Whether this is the user's first visit ever */
412
+ isFirstVisit: boolean;
413
+ /** Total visits across all sessions (lifetime) */
414
+ totalVisits: number;
415
+ /** Visits in current session */
416
+ sessionVisits: number;
417
+ /** Timestamp of first visit (unix ms) */
418
+ firstVisitTime?: number;
419
+ /** Timestamp of last visit (unix ms) */
420
+ lastVisitTime?: number;
421
+ /** Timestamp of current visit (unix ms) */
422
+ timestamp: number;
423
+ }
424
+ /**
425
+ * Page visits plugin API
426
+ */
427
+ interface PageVisitsPlugin {
428
+ /**
429
+ * Get total visit count (lifetime)
430
+ */
431
+ getTotalCount(): number;
432
+ /**
433
+ * Get session visit count
434
+ */
435
+ getSessionCount(): number;
436
+ /**
437
+ * Check if this is the first visit
438
+ */
439
+ isFirstVisit(): boolean;
440
+ /**
441
+ * Get timestamp of first visit
442
+ */
443
+ getFirstVisitTime(): number | undefined;
444
+ /**
445
+ * Get timestamp of last visit
446
+ */
447
+ getLastVisitTime(): number | undefined;
448
+ /**
449
+ * Manually increment page visit
450
+ * (useful if autoIncrement is disabled)
451
+ */
452
+ increment(): void;
453
+ /**
454
+ * Reset all counters and data
455
+ * (useful for testing or user opt-out)
456
+ */
457
+ reset(): void;
458
+ /**
459
+ * Get full page visits state
460
+ */
461
+ getState(): PageVisitsEvent;
462
+ }
463
+
464
+ /**
465
+ * Page Visits Plugin
466
+ *
467
+ * Generic page visit tracking for any SDK built on sdk-kit.
468
+ *
469
+ * Features:
470
+ * - Session-scoped counter (sessionStorage)
471
+ * - Lifetime counter with timestamps (localStorage)
472
+ * - First-visit detection
473
+ * - DNT (Do Not Track) support
474
+ * - GDPR-compliant expiration
475
+ * - Auto-loads storage plugin if missing
476
+ *
477
+ * Events emitted:
478
+ * - 'pageVisits:incremented' with PageVisitsEvent
479
+ * - 'pageVisits:reset'
480
+ * - 'pageVisits:disabled' with { reason: 'dnt' | 'config' }
481
+ *
482
+ * @example
483
+ * ```typescript
484
+ * import { SDK } from '@lytics/sdk-kit';
485
+ * import { storagePlugin, pageVisitsPlugin } from '@lytics/sdk-kit-plugins';
486
+ *
487
+ * const sdk = new SDK({
488
+ * pageVisits: {
489
+ * enabled: true,
490
+ * respectDNT: true,
491
+ * ttl: 31536000 // 1 year
492
+ * }
493
+ * });
494
+ *
495
+ * sdk.use(storagePlugin);
496
+ * sdk.use(pageVisitsPlugin);
497
+ *
498
+ * // Listen to visit events
499
+ * sdk.on('pageVisits:incremented', (event) => {
500
+ * console.log('Visit count:', event.totalVisits);
501
+ * if (event.isFirstVisit) {
502
+ * console.log('Welcome, first-time visitor!');
503
+ * }
504
+ * });
505
+ *
506
+ * // API methods
507
+ * console.log(sdk.pageVisits.getTotalCount()); // 5
508
+ * console.log(sdk.pageVisits.getSessionCount()); // 2
509
+ * console.log(sdk.pageVisits.isFirstVisit()); // false
510
+ * ```
511
+ */
512
+
513
+ declare const pageVisitsPlugin: PluginFunction;
514
+
515
+ /** @module scrollDepthPlugin */
516
+
517
+ /**
518
+ * Scroll Depth Plugin
519
+ *
520
+ * Tracks scroll depth and emits `trigger:scrollDepth` events when thresholds are crossed.
521
+ *
522
+ * ## How It Works
523
+ *
524
+ * 1. **Detection**: Listens to `scroll` events (throttled)
525
+ * 2. **Calculation**: Calculates current scroll percentage
526
+ * 3. **Tracking**: Tracks maximum scroll depth and threshold crossings
527
+ * 4. **Emission**: Emits `trigger:scrollDepth` events when thresholds are crossed
528
+ *
529
+ * ## Configuration
530
+ *
531
+ * ```typescript
532
+ * init({
533
+ * scrollDepth: {
534
+ * thresholds: [25, 50, 75, 100], // Percentages to track
535
+ * throttle: 100, // Throttle interval (ms)
536
+ * includeViewportHeight: true, // Calculation method
537
+ * recalculateOnResize: true // Recalculate on resize
538
+ * }
539
+ * });
540
+ * ```
541
+ *
542
+ * ## Experience Targeting
543
+ *
544
+ * ```typescript
545
+ * register('mid-article-cta', {
546
+ * type: 'banner',
547
+ * content: { message: 'Enjoying the article?' },
548
+ * targeting: {
549
+ * custom: (ctx) => (ctx.triggers?.scrollDepth?.percent || 0) >= 50
550
+ * }
551
+ * });
552
+ * ```
553
+ *
554
+ * ## API Methods
555
+ *
556
+ * ```typescript
557
+ * // Get maximum scroll percentage reached
558
+ * instance.scrollDepth.getMaxPercent(); // 73
559
+ *
560
+ * // Get current scroll percentage
561
+ * instance.scrollDepth.getCurrentPercent(); // 50
562
+ *
563
+ * // Get all crossed thresholds
564
+ * instance.scrollDepth.getThresholdsCrossed(); // [25, 50]
565
+ *
566
+ * // Reset tracking (useful for testing)
567
+ * instance.scrollDepth.reset();
568
+ * ```
569
+ *
570
+ * @param plugin Plugin interface from sdk-kit
571
+ * @param instance SDK instance
572
+ * @param config SDK configuration
573
+ */
574
+ declare const scrollDepthPlugin: PluginFunction;
575
+
576
+ /** @module scrollDepthPlugin */
577
+ /**
578
+ * Scroll Depth Plugin API
579
+ */
580
+ interface ScrollDepthPlugin {
581
+ getMaxPercent(): number;
582
+ getCurrentPercent(): number;
583
+ getThresholdsCrossed(): number[];
584
+ getDevice(): 'mobile' | 'tablet' | 'desktop';
585
+ getAdvancedMetrics(): {
586
+ timeOnPage: number;
587
+ directionChanges: number;
588
+ timeScrollingUp: number;
589
+ thresholdTimes: Record<number, number>;
590
+ } | null;
591
+ reset(): void;
592
+ }
593
+ /**
594
+ * Scroll Depth Plugin Configuration
595
+ *
596
+ * Tracks scroll depth and emits trigger:scrollDepth events when thresholds are crossed.
597
+ */
598
+ interface ScrollDepthPluginConfig {
599
+ scrollDepth?: {
600
+ /**
601
+ * Array of scroll percentage thresholds to track (0-100).
602
+ * When user scrolls past a threshold, a trigger:scrollDepth event is emitted.
603
+ * @default [25, 50, 75, 100]
604
+ * @example [50, 100]
605
+ */
606
+ thresholds?: number[];
607
+ /**
608
+ * Throttle interval in milliseconds for scroll event handler.
609
+ * Lower values are more responsive but impact performance.
610
+ * @default 100
611
+ * @example 200
612
+ */
613
+ throttle?: number;
614
+ /**
615
+ * Include viewport height in scroll percentage calculation.
616
+ *
617
+ * - true: (scrollTop + viewportHeight) / totalHeight
618
+ * More intuitive: 100% when bottom of viewport reaches end
619
+ * - false: scrollTop / (totalHeight - viewportHeight)
620
+ * Pathfora's method: 100% when top of viewport reaches end
621
+ *
622
+ * @default true
623
+ */
624
+ includeViewportHeight?: boolean;
625
+ /**
626
+ * Recalculate scroll on window resize.
627
+ * Useful for responsive layouts where content height changes.
628
+ * @default true
629
+ */
630
+ recalculateOnResize?: boolean;
631
+ /**
632
+ * Track advanced metrics (velocity, direction, time-to-threshold).
633
+ * Enables advanced engagement quality analysis.
634
+ * Slight performance overhead but provides rich insights.
635
+ * @default false
636
+ */
637
+ trackAdvancedMetrics?: boolean;
638
+ /**
639
+ * Velocity threshold (px/ms) to consider "fast scrolling".
640
+ * Fast scrolling often indicates skimming rather than reading.
641
+ * Only used when trackAdvancedMetrics is true.
642
+ * @default 3
643
+ */
644
+ fastScrollVelocityThreshold?: number;
645
+ /**
646
+ * Disable scroll tracking on mobile devices.
647
+ * Useful since mobile scroll behavior differs significantly from desktop.
648
+ * @default false
649
+ */
650
+ disableOnMobile?: boolean;
651
+ };
652
+ }
653
+ /**
654
+ * Scroll Depth Event Payload
655
+ *
656
+ * Emitted as `trigger:scrollDepth` when a threshold is crossed.
657
+ */
658
+ interface ScrollDepthEvent {
659
+ /** Whether the trigger has fired */
660
+ triggered: boolean;
661
+ /** Timestamp when the event was emitted */
662
+ timestamp: number;
663
+ /** Current scroll percentage (0-100) */
664
+ percent: number;
665
+ /** Maximum scroll percentage reached during session */
666
+ maxPercent: number;
667
+ /** The threshold that was just crossed */
668
+ threshold: number;
669
+ /** All thresholds that have been triggered */
670
+ thresholdsCrossed: number[];
671
+ /** Device type (mobile, tablet, desktop) */
672
+ device: 'mobile' | 'tablet' | 'desktop';
673
+ /** Advanced metrics (only present when trackAdvancedMetrics is enabled) */
674
+ advanced?: {
675
+ /** Time in milliseconds to reach this threshold from page load */
676
+ timeToThreshold: number;
677
+ /** Current scroll velocity in pixels per millisecond */
678
+ velocity: number;
679
+ /** Whether user is scrolling fast (indicates skimming) */
680
+ isFastScrolling: boolean;
681
+ /** Number of direction changes (up/down) since last threshold */
682
+ directionChanges: number;
683
+ /** Total time spent scrolling up (indicates seeking behavior) */
684
+ timeScrollingUp: number;
685
+ /** Scroll quality score (0-100, higher = more engaged) */
686
+ engagementScore: number;
687
+ };
688
+ }
689
+
690
+ /** @module timeDelayPlugin */
691
+ /**
692
+ * Time Delay Plugin Configuration
693
+ *
694
+ * Tracks time elapsed since SDK initialization and emits trigger:timeDelay events.
695
+ */
696
+ interface TimeDelayPluginConfig {
697
+ timeDelay?: {
698
+ /**
699
+ * Delay before emitting trigger event (milliseconds).
700
+ * Set to 0 to disable (immediate trigger on init).
701
+ * @default 0
702
+ * @example 5000 // 5 seconds
703
+ */
704
+ delay?: number;
705
+ /**
706
+ * Pause timer when tab is hidden (Page Visibility API).
707
+ * When true, only counts "active viewing time".
708
+ * When false, timer runs even when tab is hidden.
709
+ * @default true
710
+ */
711
+ pauseWhenHidden?: boolean;
712
+ };
713
+ }
714
+ /**
715
+ * Time Delay Event Payload
716
+ *
717
+ * Emitted via 'trigger:timeDelay' when the configured delay is reached.
718
+ */
719
+ interface TimeDelayEvent {
720
+ /** Timestamp when the trigger event was emitted */
721
+ timestamp: number;
722
+ /** Total elapsed time since init (milliseconds, includes paused time) */
723
+ elapsed: number;
724
+ /** Active elapsed time (milliseconds, excludes time when tab was hidden) */
725
+ activeElapsed: number;
726
+ /** Whether the timer was paused at any point */
727
+ wasPaused: boolean;
728
+ /** Number of times visibility changed (hidden/visible) */
729
+ visibilityChanges: number;
730
+ }
731
+ /**
732
+ * Time Delay Plugin API
733
+ */
734
+ interface TimeDelayPlugin {
735
+ /**
736
+ * Get total elapsed time since init (includes paused time)
737
+ * @returns Time in milliseconds
738
+ */
739
+ getElapsed(): number;
740
+ /**
741
+ * Get active elapsed time (excludes paused time)
742
+ * @returns Time in milliseconds
743
+ */
744
+ getActiveElapsed(): number;
745
+ /**
746
+ * Get remaining time until trigger
747
+ * @returns Time in milliseconds, or 0 if already triggered
748
+ */
749
+ getRemaining(): number;
750
+ /**
751
+ * Check if timer is currently paused (tab hidden)
752
+ * @returns True if paused
753
+ */
754
+ isPaused(): boolean;
755
+ /**
756
+ * Check if trigger has fired
757
+ * @returns True if triggered
758
+ */
759
+ isTriggered(): boolean;
760
+ /**
761
+ * Reset timer to initial state
762
+ * Clears trigger flag and restarts timing
763
+ */
764
+ reset(): void;
765
+ }
766
+
767
+ /** @module timeDelayPlugin */
768
+
769
+ /**
770
+ * Time Delay Plugin
771
+ *
772
+ * Tracks time elapsed since SDK initialization and emits trigger:timeDelay events
773
+ * when the configured delay is reached.
774
+ *
775
+ * **Features:**
776
+ * - Millisecond precision timing
777
+ * - Pause/resume on tab visibility change (optional)
778
+ * - Tracks active vs total elapsed time
779
+ * - Full timer lifecycle management
780
+ *
781
+ * **Event-Driven Architecture:**
782
+ * This plugin emits `trigger:timeDelay` events when the delay threshold is reached.
783
+ * The core runtime listens for these events and automatically re-evaluates experiences.
784
+ *
785
+ * **Usage Pattern:**
786
+ * Use `targeting.custom` to check if time delay has triggered:
787
+ *
788
+ * @example Basic usage
789
+ * ```typescript
790
+ * import { init, register } from '@prosdevlab/experience-sdk';
791
+ *
792
+ * init({
793
+ * timeDelay: {
794
+ * delay: 5000, // 5 seconds
795
+ * pauseWhenHidden: true // Pause when tab hidden (default)
796
+ * }
797
+ * });
798
+ *
799
+ * // Show banner after 5 seconds of active viewing time
800
+ * register('timed-offer', {
801
+ * type: 'banner',
802
+ * content: {
803
+ * message: 'Limited time offer!',
804
+ * buttons: [{ text: 'Claim Now', variant: 'primary' }]
805
+ * },
806
+ * targeting: {
807
+ * custom: (context) => {
808
+ * const active = context.triggers?.timeDelay?.activeElapsed || 0;
809
+ * return active >= 5000;
810
+ * }
811
+ * }
812
+ * });
813
+ * ```
814
+ *
815
+ * @example Combining with other triggers
816
+ * ```typescript
817
+ * // Show after 10s OR on exit intent (whichever comes first)
818
+ * register('engaged-offer', {
819
+ * type: 'banner',
820
+ * content: { message: 'Special offer for engaged users!' },
821
+ * targeting: {
822
+ * custom: (context) => {
823
+ * const timeElapsed = (context.triggers?.timeDelay?.activeElapsed || 0) >= 10000;
824
+ * const exitIntent = context.triggers?.exitIntent?.triggered;
825
+ * return timeElapsed || exitIntent;
826
+ * }
827
+ * }
828
+ * });
829
+ * ```
830
+ *
831
+ * @param plugin Plugin interface from sdk-kit
832
+ * @param instance SDK instance
833
+ * @param config SDK configuration
834
+ */
835
+ declare const timeDelayPlugin: PluginFunction;
836
+
837
+ export { type BannerContent, type BannerPlugin, type BannerPluginConfig, type DebugPlugin, type DebugPluginConfig, type Decision, type DecisionMetadata, type ExitIntentEvent, type ExitIntentPlugin, type ExitIntentPluginConfig, type Experience, type ExperienceContent, type FrequencyPlugin, type FrequencyPluginConfig, type ModalContent, type PageVisitsEvent, type PageVisitsPlugin, type PageVisitsPluginConfig, type ScrollDepthEvent, type ScrollDepthPlugin, type ScrollDepthPluginConfig, type TimeDelayEvent, type TimeDelayPlugin, type TimeDelayPluginConfig, type TooltipContent, type TraceStep, bannerPlugin, debugPlugin, exitIntentPlugin, frequencyPlugin, pageVisitsPlugin, scrollDepthPlugin, timeDelayPlugin };