@prosdevlab/experience-sdk-plugins 0.2.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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +120 -0
- package/README.md +141 -79
- package/dist/index.d.ts +206 -35
- package/dist/index.js +1229 -75
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/banner/banner.ts +63 -62
- package/src/exit-intent/exit-intent.ts +2 -3
- package/src/index.ts +2 -0
- package/src/inline/index.ts +3 -0
- package/src/inline/inline.test.ts +620 -0
- package/src/inline/inline.ts +269 -0
- package/src/inline/insertion.ts +66 -0
- package/src/inline/types.ts +52 -0
- package/src/integration.test.ts +356 -297
- package/src/modal/form-rendering.ts +262 -0
- package/src/modal/form-styles.ts +212 -0
- package/src/modal/form-validation.test.ts +413 -0
- package/src/modal/form-validation.ts +126 -0
- package/src/modal/index.ts +3 -0
- package/src/modal/modal-styles.ts +204 -0
- package/src/modal/modal.browser.test.ts +164 -0
- package/src/modal/modal.test.ts +1294 -0
- package/src/modal/modal.ts +685 -0
- package/src/modal/types.ts +114 -0
- package/src/scroll-depth/scroll-depth.test.ts +35 -0
- package/src/scroll-depth/scroll-depth.ts +2 -4
- package/src/time-delay/time-delay.test.ts +2 -2
- package/src/time-delay/time-delay.ts +2 -3
- package/src/types.ts +20 -36
- package/src/utils/sanitize.ts +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,57 +1,187 @@
|
|
|
1
|
-
import { PluginFunction } from '@lytics/sdk-kit';
|
|
1
|
+
import { PluginFunction, SDK } from '@lytics/sdk-kit';
|
|
2
|
+
export { PluginFunction } from '@lytics/sdk-kit';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
* These types are re-exported by core for user convenience
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Experience content - varies by type
|
|
5
|
+
* Inline plugin configuration
|
|
9
6
|
*/
|
|
10
|
-
|
|
7
|
+
interface InlinePluginConfig {
|
|
8
|
+
inline?: {
|
|
9
|
+
/** Retry selector lookup if not found (default: false) */
|
|
10
|
+
retry?: boolean;
|
|
11
|
+
/** Retry timeout in ms (default: 5000) */
|
|
12
|
+
retryTimeout?: number;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
11
15
|
/**
|
|
12
|
-
*
|
|
16
|
+
* Inline content configuration
|
|
13
17
|
*/
|
|
14
|
-
interface
|
|
15
|
-
|
|
18
|
+
interface InlineContent$1 {
|
|
19
|
+
/** CSS selector for target element */
|
|
20
|
+
selector: string;
|
|
21
|
+
/** Where to insert content (default: 'replace') */
|
|
22
|
+
position?: 'replace' | 'append' | 'prepend' | 'before' | 'after';
|
|
23
|
+
/** HTML content to insert */
|
|
16
24
|
message: string;
|
|
17
|
-
|
|
18
|
-
text: string;
|
|
19
|
-
action?: string;
|
|
20
|
-
url?: string;
|
|
21
|
-
variant?: 'primary' | 'secondary' | 'link';
|
|
22
|
-
metadata?: Record<string, any>;
|
|
23
|
-
className?: string;
|
|
24
|
-
style?: Record<string, string>;
|
|
25
|
-
}>;
|
|
25
|
+
/** Show close button (default: false) */
|
|
26
26
|
dismissable?: boolean;
|
|
27
|
-
|
|
27
|
+
/** Remember dismissal in localStorage (default: false) */
|
|
28
|
+
persist?: boolean;
|
|
29
|
+
/** Custom CSS class */
|
|
28
30
|
className?: string;
|
|
31
|
+
/** Inline styles */
|
|
29
32
|
style?: Record<string, string>;
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
35
|
+
* Inline plugin API
|
|
33
36
|
*/
|
|
34
|
-
interface
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
interface InlinePlugin {
|
|
38
|
+
/** Show an inline experience */
|
|
39
|
+
show(experience: any): void;
|
|
40
|
+
/** Remove a specific inline experience */
|
|
41
|
+
remove(experienceId: string): void;
|
|
42
|
+
/** Check if an inline experience is showing */
|
|
43
|
+
isShowing(experienceId?: string): boolean;
|
|
39
44
|
}
|
|
40
45
|
/**
|
|
41
|
-
*
|
|
46
|
+
* Insertion position for inline content
|
|
42
47
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
48
|
+
type InsertionPosition = 'replace' | 'append' | 'prepend' | 'before' | 'after';
|
|
49
|
+
|
|
50
|
+
interface ModalConfig {
|
|
51
|
+
modal?: {
|
|
52
|
+
/** Allow dismissal via close button (default: true) */
|
|
53
|
+
dismissable?: boolean;
|
|
54
|
+
/** Allow dismissal via backdrop click (default: true) */
|
|
55
|
+
backdropDismiss?: boolean;
|
|
56
|
+
/** Z-index for modal (default: 10001) */
|
|
57
|
+
zIndex?: number;
|
|
58
|
+
/** Modal size (default: 'md') */
|
|
59
|
+
size?: 'sm' | 'md' | 'lg' | 'fullscreen' | 'auto';
|
|
60
|
+
/** Auto-fullscreen on mobile screens <640px (default: true for 'lg', false for others) */
|
|
61
|
+
mobileFullscreen?: boolean;
|
|
62
|
+
/** Modal position (default: 'center') */
|
|
63
|
+
position?: 'center' | 'bottom';
|
|
64
|
+
/** Animation type (default: 'fade') */
|
|
65
|
+
animation?: 'fade' | 'slide-up' | 'none';
|
|
66
|
+
/** Animation duration in ms (default: 200) */
|
|
67
|
+
animationDuration?: number;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
interface ModalContent$1 {
|
|
71
|
+
/** Optional hero image at top of modal */
|
|
72
|
+
image?: {
|
|
73
|
+
/** Image source URL */
|
|
74
|
+
src: string;
|
|
75
|
+
/** Alt text for accessibility */
|
|
76
|
+
alt: string;
|
|
77
|
+
/** Max height in pixels (default: 300, 200 on mobile) */
|
|
78
|
+
maxHeight?: number;
|
|
79
|
+
};
|
|
80
|
+
/** Modal title */
|
|
81
|
+
title?: string;
|
|
82
|
+
/** Modal message (supports HTML via sanitizer) */
|
|
45
83
|
message: string;
|
|
46
|
-
|
|
47
|
-
|
|
84
|
+
/** Array of action buttons */
|
|
85
|
+
buttons?: ExperienceButton[];
|
|
86
|
+
/** Optional form configuration */
|
|
87
|
+
form?: FormConfig;
|
|
88
|
+
/** Custom CSS class */
|
|
89
|
+
className?: string;
|
|
90
|
+
/** Inline styles */
|
|
91
|
+
style?: Record<string, string>;
|
|
92
|
+
}
|
|
93
|
+
interface FormConfig {
|
|
94
|
+
/** Array of form fields */
|
|
95
|
+
fields: FormField[];
|
|
96
|
+
/** Submit button configuration */
|
|
97
|
+
submitButton: ExperienceButton;
|
|
98
|
+
/** Success state after submission */
|
|
99
|
+
successState?: FormState;
|
|
100
|
+
/** Error state on submission failure */
|
|
101
|
+
errorState?: FormState;
|
|
102
|
+
/** Custom validation function (optional) */
|
|
103
|
+
validate?: (data: Record<string, string>) => ValidationResult;
|
|
104
|
+
}
|
|
105
|
+
interface FormField {
|
|
106
|
+
/** Field name (used in form data) */
|
|
107
|
+
name: string;
|
|
108
|
+
/** Field type */
|
|
109
|
+
type: 'email' | 'text' | 'textarea' | 'tel' | 'url' | 'number';
|
|
110
|
+
/** Label text (optional) */
|
|
111
|
+
label?: string;
|
|
112
|
+
/** Placeholder text */
|
|
113
|
+
placeholder?: string;
|
|
114
|
+
/** Required field (default: false) */
|
|
115
|
+
required?: boolean;
|
|
116
|
+
/** Custom validation pattern (regex) */
|
|
117
|
+
pattern?: string;
|
|
118
|
+
/** Error message for validation failure */
|
|
119
|
+
errorMessage?: string;
|
|
120
|
+
/** Custom CSS class */
|
|
121
|
+
className?: string;
|
|
122
|
+
/** Inline styles */
|
|
123
|
+
style?: Record<string, string>;
|
|
48
124
|
}
|
|
125
|
+
interface FormState {
|
|
126
|
+
/** Title to show in success/error state */
|
|
127
|
+
title?: string;
|
|
128
|
+
/** Message to show */
|
|
129
|
+
message: string;
|
|
130
|
+
/** Optional buttons (e.g., "Close", "Try Again") */
|
|
131
|
+
buttons?: ExperienceButton[];
|
|
132
|
+
}
|
|
133
|
+
interface ValidationResult {
|
|
134
|
+
/** Whether validation passed */
|
|
135
|
+
valid: boolean;
|
|
136
|
+
/** Validation errors by field name */
|
|
137
|
+
errors?: Record<string, string>;
|
|
138
|
+
}
|
|
139
|
+
interface ModalPlugin {
|
|
140
|
+
/** Show a modal experience */
|
|
141
|
+
show(experience: any): void;
|
|
142
|
+
/** Remove a specific modal */
|
|
143
|
+
remove(experienceId: string): void;
|
|
144
|
+
/** Check if a modal is showing */
|
|
145
|
+
isShowing(experienceId?: string): boolean;
|
|
146
|
+
/** Show form success or error state */
|
|
147
|
+
showFormState(experienceId: string, state: 'success' | 'error'): void;
|
|
148
|
+
/** Reset form to initial state */
|
|
149
|
+
resetForm(experienceId: string): void;
|
|
150
|
+
/** Get current form data */
|
|
151
|
+
getFormData(experienceId: string): Record<string, string> | null;
|
|
152
|
+
}
|
|
153
|
+
|
|
49
154
|
/**
|
|
50
|
-
*
|
|
155
|
+
* Shared types for Experience SDK plugins
|
|
156
|
+
* These types are re-exported by core for user convenience
|
|
51
157
|
*/
|
|
52
|
-
|
|
158
|
+
|
|
159
|
+
type ModalContent = ModalContent$1;
|
|
160
|
+
type InlineContent = InlineContent$1;
|
|
161
|
+
/**
|
|
162
|
+
* Experience button configuration (used across all experience types)
|
|
163
|
+
*/
|
|
164
|
+
interface ExperienceButton {
|
|
165
|
+
text: string;
|
|
166
|
+
action?: string;
|
|
167
|
+
url?: string;
|
|
168
|
+
variant?: 'primary' | 'secondary' | 'link';
|
|
169
|
+
dismiss?: boolean;
|
|
170
|
+
metadata?: Record<string, any>;
|
|
171
|
+
className?: string;
|
|
172
|
+
style?: Record<string, string>;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Banner content configuration
|
|
176
|
+
*/
|
|
177
|
+
interface BannerContent {
|
|
178
|
+
title?: string;
|
|
53
179
|
message: string;
|
|
54
|
-
|
|
180
|
+
buttons?: ExperienceButton[];
|
|
181
|
+
dismissable?: boolean;
|
|
182
|
+
position?: 'top' | 'bottom';
|
|
183
|
+
className?: string;
|
|
184
|
+
style?: Record<string, string>;
|
|
55
185
|
}
|
|
56
186
|
/**
|
|
57
187
|
* Tooltip content configuration
|
|
@@ -60,6 +190,10 @@ interface TooltipContent {
|
|
|
60
190
|
message: string;
|
|
61
191
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
62
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* Experience content - varies by type
|
|
195
|
+
*/
|
|
196
|
+
type ExperienceContent = BannerContent | ModalContent | InlineContent | TooltipContent;
|
|
63
197
|
/**
|
|
64
198
|
* Experience definition
|
|
65
199
|
*/
|
|
@@ -361,6 +495,43 @@ interface FrequencyPlugin {
|
|
|
361
495
|
*/
|
|
362
496
|
declare const frequencyPlugin: PluginFunction;
|
|
363
497
|
|
|
498
|
+
/**
|
|
499
|
+
* Inline Plugin
|
|
500
|
+
*
|
|
501
|
+
* Embeds experiences directly within page content using DOM selectors.
|
|
502
|
+
* Supports multiple insertion positions and dismissal with persistence.
|
|
503
|
+
*/
|
|
504
|
+
declare const inlinePlugin: (plugin: any, instance: SDK, config: any) => void;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Insert content into a target element using specified position
|
|
508
|
+
*
|
|
509
|
+
* @param selector - CSS selector for target element
|
|
510
|
+
* @param content - HTML content to insert
|
|
511
|
+
* @param position - Where to insert the content
|
|
512
|
+
* @param experienceId - Unique identifier for the experience
|
|
513
|
+
* @returns The created wrapper element, or null if target not found
|
|
514
|
+
*/
|
|
515
|
+
declare function insertContent(selector: string, content: string, position: InsertionPosition, experienceId: string): HTMLElement | null;
|
|
516
|
+
/**
|
|
517
|
+
* Remove inline content by experience ID
|
|
518
|
+
*
|
|
519
|
+
* @param experienceId - Unique identifier for the experience
|
|
520
|
+
* @returns True if element was found and removed, false otherwise
|
|
521
|
+
*/
|
|
522
|
+
declare function removeContent(experienceId: string): boolean;
|
|
523
|
+
|
|
524
|
+
/**
|
|
525
|
+
* Modal Plugin for @prosdevlab/experience-sdk
|
|
526
|
+
*
|
|
527
|
+
* Renders experiences as accessible modal dialogs with:
|
|
528
|
+
* - Focus trap and keyboard handling
|
|
529
|
+
* - ARIA attributes for screen readers
|
|
530
|
+
* - Backdrop and close button
|
|
531
|
+
* - Responsive design
|
|
532
|
+
*/
|
|
533
|
+
declare const modalPlugin: (plugin: any, instance: SDK) => void;
|
|
534
|
+
|
|
364
535
|
/**
|
|
365
536
|
* Page Visits Plugin Types
|
|
366
537
|
*
|
|
@@ -834,4 +1005,4 @@ interface TimeDelayPlugin {
|
|
|
834
1005
|
*/
|
|
835
1006
|
declare const timeDelayPlugin: PluginFunction;
|
|
836
1007
|
|
|
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 };
|
|
1008
|
+
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 FormConfig, type FormField, type FormState, type FrequencyPlugin, type FrequencyPluginConfig, type InlineContent$1 as InlineContent, type InlinePlugin, type InlinePluginConfig, type InsertionPosition, type ModalConfig, type ModalContent, type ModalPlugin, type PageVisitsEvent, type PageVisitsPlugin, type PageVisitsPluginConfig, type ScrollDepthEvent, type ScrollDepthPlugin, type ScrollDepthPluginConfig, type TimeDelayEvent, type TimeDelayPlugin, type TimeDelayPluginConfig, type TooltipContent, type TraceStep, type ValidationResult, bannerPlugin, debugPlugin, exitIntentPlugin, frequencyPlugin, inlinePlugin, insertContent, modalPlugin, pageVisitsPlugin, removeContent, scrollDepthPlugin, timeDelayPlugin };
|