@encatch/web-sdk 0.0.35 → 1.0.0-beta.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/README.md +140 -638
- package/dist/encatch.es.js +2 -0
- package/dist/encatch.es.js.map +1 -0
- package/dist/encatch.iife.js +2 -0
- package/dist/encatch.iife.js.map +1 -0
- package/dist/index.d.ts +191 -0
- package/package.json +32 -50
- package/dist-sdk/plugin/sdk/core-wrapper-BMvOyc0u.js +0 -22926
- package/dist-sdk/plugin/sdk/module-DC2Edddk.js +0 -481
- package/dist-sdk/plugin/sdk/module.js +0 -5
- package/dist-sdk/plugin/sdk/preview-sdk.html +0 -1182
- package/dist-sdk/plugin/sdk/vite.svg +0 -15
- package/dist-sdk/plugin/sdk/web-form-engine-core.css +0 -1
- package/index.d.ts +0 -207
- package/src/@types/encatch-type.ts +0 -111
- package/src/encatch-instance.ts +0 -161
- package/src/feedback-api-types.ts +0 -18
- package/src/hooks/useDevice.ts +0 -30
- package/src/hooks/useFeedbackInterval.ts +0 -71
- package/src/hooks/useFeedbackTriggers.ts +0 -342
- package/src/hooks/useFetchElligibleFeedbackConfiguration.ts +0 -363
- package/src/hooks/useFetchFeedbackConfigurationDetails.ts +0 -92
- package/src/hooks/usePageChangeTracker.ts +0 -88
- package/src/hooks/usePrepopulatedAnswers.ts +0 -123
- package/src/hooks/useRefineTextForm.ts +0 -55
- package/src/hooks/useSubmitFeedbackForm.ts +0 -134
- package/src/hooks/useUserSession.ts +0 -53
- package/src/module.tsx +0 -428
- package/src/store/formResponses.ts +0 -211
- package/src/utils/browser-details.ts +0 -36
- package/src/utils/duration-utils.ts +0 -158
- package/src/utils/feedback-frequency-storage.ts +0 -214
- package/src/utils/feedback-storage.ts +0 -166
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { EncatchApiSDK, RefineTextParams, RefineTextResponse } from "@encatch/api-sdk";
|
|
2
|
-
import { useState } from "preact/hooks";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export const useRefineTextForm = ({ apiKey, hostUrl }: { apiKey?: string; hostUrl: string }) => {
|
|
6
|
-
const [loadingRefineText, setLoadingRefineText] = useState(false);
|
|
7
|
-
const [errorRefineText, setErrorRefineText] = useState<string | null>(null);
|
|
8
|
-
const [resultRefineText, setResultRefineText] = useState<RefineTextResponse | null>(null);
|
|
9
|
-
const [successMsg, setSuccessMsg] = useState<string | null>(null);
|
|
10
|
-
|
|
11
|
-
// Instantiate the SDK once
|
|
12
|
-
const sdk = new EncatchApiSDK({
|
|
13
|
-
apiKey: apiKey || "",
|
|
14
|
-
hostUrl,
|
|
15
|
-
appPackageName: window.location.hostname,
|
|
16
|
-
enableLogging: true,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const refineText = async (params: RefineTextParams): Promise<RefineTextResponse | null> => {
|
|
20
|
-
// Prevent API calls if apiKey is blank
|
|
21
|
-
if (!apiKey || apiKey.trim() === '') {
|
|
22
|
-
console.warn('refineText: API key is required');
|
|
23
|
-
setErrorRefineText('API key is required');
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
setLoadingRefineText(true);
|
|
28
|
-
setErrorRefineText(null);
|
|
29
|
-
setResultRefineText(null);
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
// Use the SDK's refineText method
|
|
33
|
-
const result = await sdk.refineText(params);
|
|
34
|
-
|
|
35
|
-
setSuccessMsg(result.message || "Text refined successfully");
|
|
36
|
-
|
|
37
|
-
setResultRefineText(result);
|
|
38
|
-
return result;
|
|
39
|
-
} catch (err) {
|
|
40
|
-
const errorMessage = err instanceof Error ? err.message : "An error occurred while refining text";
|
|
41
|
-
setErrorRefineText(errorMessage);
|
|
42
|
-
return null;
|
|
43
|
-
} finally {
|
|
44
|
-
setLoadingRefineText(false);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
loadingRefineText,
|
|
50
|
-
errorRefineText,
|
|
51
|
-
resultRefineText,
|
|
52
|
-
refineText,
|
|
53
|
-
successMsg
|
|
54
|
-
};
|
|
55
|
-
};
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import { useState } from "preact/hooks";
|
|
2
|
-
import { SubmitFeedback, ViewFeedback } from "@encatch/schema";
|
|
3
|
-
import { EncatchApiSDK } from "@encatch/api-sdk";
|
|
4
|
-
|
|
5
|
-
export interface SubmitFeedbackResponse {
|
|
6
|
-
success?: boolean;
|
|
7
|
-
error?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const useSubmitFeedbackForm = ({
|
|
11
|
-
apiKey,
|
|
12
|
-
hostUrl,
|
|
13
|
-
}: {
|
|
14
|
-
apiKey: string;
|
|
15
|
-
hostUrl: string;
|
|
16
|
-
}) => {
|
|
17
|
-
const [loadingSubmitFeedback, setLoadingSubmitFeedback] = useState(false);
|
|
18
|
-
const [errorSubmitFeedback, setErrorSubmitFeedback] = useState<string | null>(
|
|
19
|
-
null
|
|
20
|
-
);
|
|
21
|
-
const [successSubmitFeedback, setSuccessSubmitFeedback] = useState(false);
|
|
22
|
-
|
|
23
|
-
// New state for viewFeedback
|
|
24
|
-
const [loadingViewFeedback, setLoadingViewFeedback] = useState(false);
|
|
25
|
-
const [errorViewFeedback, setErrorViewFeedback] = useState<string | null>(
|
|
26
|
-
null
|
|
27
|
-
);
|
|
28
|
-
const [successViewFeedback, setSuccessViewFeedback] = useState(false);
|
|
29
|
-
|
|
30
|
-
// Instantiate the SDK once
|
|
31
|
-
const sdk = new EncatchApiSDK({
|
|
32
|
-
apiKey,
|
|
33
|
-
hostUrl,
|
|
34
|
-
appPackageName: window.location.hostname,
|
|
35
|
-
enableLogging: true,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const submitFeedback = async (
|
|
39
|
-
params: SubmitFeedback
|
|
40
|
-
): Promise<SubmitFeedbackResponse> => {
|
|
41
|
-
// Prevent API calls if apiKey is blank
|
|
42
|
-
if (!apiKey || apiKey.trim() === '') {
|
|
43
|
-
console.warn('submitFeedback: API key is required');
|
|
44
|
-
return { error: 'API key is required' };
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
setLoadingSubmitFeedback(true);
|
|
48
|
-
setErrorSubmitFeedback(null);
|
|
49
|
-
setSuccessSubmitFeedback(false);
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
// Ensure sessionInfo is always provided (required by SDK)
|
|
53
|
-
if (!params.sessionInfo) {
|
|
54
|
-
throw new Error("sessionInfo is required for submitting feedback");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Use the SDK's submitFeedback method
|
|
58
|
-
// Type assertion needed because SDK requires sessionInfo to be non-optional
|
|
59
|
-
const result = await sdk.submitFeedback(params as any);
|
|
60
|
-
|
|
61
|
-
if (!result.success) {
|
|
62
|
-
throw new Error(result.error || "Unknown error from SDK");
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Note: moveFeedbackToSubmitted is handled in core-wrapper.tsx
|
|
66
|
-
// where it checks isManual before moving. Manual feedbacks should NOT be moved.
|
|
67
|
-
// Previously this was called here unconditionally, causing manual feedbacks to be removed.
|
|
68
|
-
|
|
69
|
-
setSuccessSubmitFeedback(true);
|
|
70
|
-
return { success: true };
|
|
71
|
-
} catch (err) {
|
|
72
|
-
const errorMessage =
|
|
73
|
-
err instanceof Error
|
|
74
|
-
? err.message
|
|
75
|
-
: "An error occurred while submitting feedback";
|
|
76
|
-
setErrorSubmitFeedback(errorMessage);
|
|
77
|
-
return { error: errorMessage };
|
|
78
|
-
} finally {
|
|
79
|
-
setLoadingSubmitFeedback(false);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const viewFeedback = async (
|
|
84
|
-
params: ViewFeedback
|
|
85
|
-
): Promise<SubmitFeedbackResponse> => {
|
|
86
|
-
// Prevent API calls if apiKey is blank
|
|
87
|
-
if (!apiKey || apiKey.trim() === '') {
|
|
88
|
-
console.warn('viewFeedback: API key is required');
|
|
89
|
-
return { error: 'API key is required' };
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
setLoadingViewFeedback(true);
|
|
93
|
-
setErrorViewFeedback(null);
|
|
94
|
-
setSuccessViewFeedback(false);
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
// Ensure sessionInfo is always provided (required by SDK)
|
|
98
|
-
if (!params.sessionInfo) {
|
|
99
|
-
throw new Error("sessionInfo is required for viewing feedback");
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Use the SDK's viewFeedback method
|
|
103
|
-
// Type assertion needed because SDK requires sessionInfo to be non-optional
|
|
104
|
-
const result = await sdk.viewFeedback(params as any);
|
|
105
|
-
|
|
106
|
-
if (!result.success) {
|
|
107
|
-
throw new Error(result.error || "Unknown error from SDK");
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
setSuccessViewFeedback(true);
|
|
111
|
-
return { success: true };
|
|
112
|
-
} catch (err) {
|
|
113
|
-
const errorMessage =
|
|
114
|
-
err instanceof Error
|
|
115
|
-
? err.message
|
|
116
|
-
: "An error occurred while viewing feedback";
|
|
117
|
-
setErrorViewFeedback(errorMessage);
|
|
118
|
-
return { error: errorMessage };
|
|
119
|
-
} finally {
|
|
120
|
-
setLoadingViewFeedback(false);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
loadingSubmitFeedback,
|
|
126
|
-
errorSubmitFeedback,
|
|
127
|
-
successSubmitFeedback,
|
|
128
|
-
submitFeedback,
|
|
129
|
-
loadingViewFeedback,
|
|
130
|
-
errorViewFeedback,
|
|
131
|
-
successViewFeedback,
|
|
132
|
-
viewFeedback,
|
|
133
|
-
};
|
|
134
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { UserInfo } from "@encatch/schema";
|
|
2
|
-
import { useState, useEffect } from "preact/hooks";
|
|
3
|
-
|
|
4
|
-
const USER_STORAGE_KEY = "encatch_app_user";
|
|
5
|
-
const SESSION_STORAGE_KEY = "app_session";
|
|
6
|
-
|
|
7
|
-
function generateSessionId() {
|
|
8
|
-
return crypto.randomUUID();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const useUserSession = () => {
|
|
12
|
-
const [userInfoObject, setUserInfoObject] = useState<UserInfo>({
|
|
13
|
-
userName: "",
|
|
14
|
-
properties: {},
|
|
15
|
-
});
|
|
16
|
-
const [sessionId, setSessionId] = useState<string | null>(null);
|
|
17
|
-
|
|
18
|
-
const updateUserInfo = (userId: string, traits?: Record<string, any>) => {
|
|
19
|
-
const newUserInfo: UserInfo = {
|
|
20
|
-
userName: userId,
|
|
21
|
-
properties: traits || {},
|
|
22
|
-
};
|
|
23
|
-
setUserInfoObject(newUserInfo);
|
|
24
|
-
localStorage.setItem(USER_STORAGE_KEY, JSON.stringify(newUserInfo));
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
// Handle session - check if there's an existing session
|
|
29
|
-
const storedSessionId = localStorage.getItem(SESSION_STORAGE_KEY);
|
|
30
|
-
if (storedSessionId) {
|
|
31
|
-
setSessionId(storedSessionId);
|
|
32
|
-
} else {
|
|
33
|
-
// Create new session if none exists
|
|
34
|
-
const newSessionId = generateSessionId();
|
|
35
|
-
localStorage.setItem(SESSION_STORAGE_KEY, newSessionId);
|
|
36
|
-
setSessionId(newSessionId);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Handle user info
|
|
40
|
-
const storedUser = localStorage.getItem(USER_STORAGE_KEY);
|
|
41
|
-
if (storedUser) {
|
|
42
|
-
setUserInfoObject(JSON.parse(storedUser));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
}, []);
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
userInfoObject,
|
|
49
|
-
updateUserInfo,
|
|
50
|
-
sessionId,
|
|
51
|
-
setUserInfoObject,
|
|
52
|
-
};
|
|
53
|
-
};
|
package/src/module.tsx
DELETED
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module entry point for @encatch/web-sdk
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* ```typescript
|
|
6
|
-
* import { Encatch } from '@encatch/web-sdk';
|
|
7
|
-
*
|
|
8
|
-
* const encatch = new Encatch();
|
|
9
|
-
* encatch.init('YOUR_API_KEY', {
|
|
10
|
-
* host: 'https://your-host.com',
|
|
11
|
-
* autoStartEnabled: true
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { createEncatchInstance } from "./encatch-instance";
|
|
17
|
-
import { EncatchConfig, FormEventType, FormEventPayload } from "./@types/encatch-type";
|
|
18
|
-
// Import render statically to avoid dynamic/static import conflict with preact
|
|
19
|
-
import { render } from "preact";
|
|
20
|
-
|
|
21
|
-
let coreLoaded = false;
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Load the core wrapper for module usage
|
|
25
|
-
* SSR-safe: Only runs in browser environment
|
|
26
|
-
*/
|
|
27
|
-
async function loadCore() {
|
|
28
|
-
// SSR safety check
|
|
29
|
-
if (coreLoaded || typeof window === "undefined" || typeof document === "undefined") return;
|
|
30
|
-
coreLoaded = true;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
// Dynamically import the core wrapper (preact render is already imported statically)
|
|
34
|
-
const CoreWrapper = (await import("./core-wrapper")).default;
|
|
35
|
-
|
|
36
|
-
// Ensure root exists (SSR-safe)
|
|
37
|
-
if (typeof document === "undefined") return;
|
|
38
|
-
|
|
39
|
-
let root = document.getElementById("enisght-root");
|
|
40
|
-
if (!root && document.body) {
|
|
41
|
-
root = document.createElement("div");
|
|
42
|
-
root.id = "enisght-root";
|
|
43
|
-
document.body.appendChild(root);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Render the core wrapper (only if we have a root)
|
|
47
|
-
if (root) {
|
|
48
|
-
render(<CoreWrapper />, root);
|
|
49
|
-
}
|
|
50
|
-
} catch (err) {
|
|
51
|
-
console.error("Failed to load Encatch core:", err);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Singleton instance for static API
|
|
56
|
-
let defaultInstance: Encatch | null = null;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Encatch SDK class for module-based usage
|
|
60
|
-
*/
|
|
61
|
-
export class Encatch {
|
|
62
|
-
private instance: EncatchGlobal;
|
|
63
|
-
|
|
64
|
-
constructor() {
|
|
65
|
-
this.instance = createEncatchInstance();
|
|
66
|
-
|
|
67
|
-
// Sync instance with window.encatch for core-wrapper compatibility
|
|
68
|
-
// This ensures core-wrapper can access the instance
|
|
69
|
-
if (typeof window !== "undefined") {
|
|
70
|
-
// Only set if not already set (to avoid overwriting CDN version)
|
|
71
|
-
if (!window.encatch) {
|
|
72
|
-
window.encatch = this.instance;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Ensure the root div exists (SSR-safe)
|
|
77
|
-
if (typeof window !== "undefined" && typeof document !== "undefined") {
|
|
78
|
-
if (!document.getElementById("enisght-root")) {
|
|
79
|
-
const rootDiv = document.createElement("div");
|
|
80
|
-
rootDiv.id = "enisght-root";
|
|
81
|
-
if (document.body) {
|
|
82
|
-
document.body.appendChild(rootDiv);
|
|
83
|
-
} else {
|
|
84
|
-
// Wait for DOM to be ready
|
|
85
|
-
if (document.readyState === "loading") {
|
|
86
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
87
|
-
if (!document.getElementById("enisght-root") && document.body) {
|
|
88
|
-
document.body.appendChild(rootDiv);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Static method to initialize the default Encatch instance
|
|
99
|
-
* This provides a convenient API: Encatch.init(apiKey, options)
|
|
100
|
-
*/
|
|
101
|
-
static init(apiKey: string, options?: EncatchConfig): Encatch {
|
|
102
|
-
if (!defaultInstance) {
|
|
103
|
-
defaultInstance = new Encatch();
|
|
104
|
-
}
|
|
105
|
-
defaultInstance.init(apiKey, options);
|
|
106
|
-
return defaultInstance;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Get the default singleton instance
|
|
111
|
-
*/
|
|
112
|
-
static getInstance(): Encatch {
|
|
113
|
-
if (!defaultInstance) {
|
|
114
|
-
defaultInstance = new Encatch();
|
|
115
|
-
}
|
|
116
|
-
return defaultInstance;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Initialize the Encatch SDK
|
|
121
|
-
* SSR-safe: Can be called on server, but only initializes in browser
|
|
122
|
-
*/
|
|
123
|
-
init(apiKey: string, options?: EncatchConfig): void {
|
|
124
|
-
// SSR safety check
|
|
125
|
-
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
126
|
-
// In SSR environment, just store config for later initialization
|
|
127
|
-
this.instance.apiKey = apiKey;
|
|
128
|
-
if (options) {
|
|
129
|
-
Object.assign(this.instance.config, options);
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Override the init to load core directly instead of via script tag
|
|
135
|
-
if (this.instance.initialized) return;
|
|
136
|
-
|
|
137
|
-
// Update all config first
|
|
138
|
-
this.instance.apiKey = apiKey;
|
|
139
|
-
// Set host with default if not provided
|
|
140
|
-
this.instance.config.host = options?.host || "https://app.encatch.com";
|
|
141
|
-
if (options?.autoStartSessionDisabled !== undefined) {
|
|
142
|
-
this.instance.config.autoStartSessionDisabled =
|
|
143
|
-
options.autoStartSessionDisabled;
|
|
144
|
-
}
|
|
145
|
-
if (options?.processAfterIdentitySet !== undefined) {
|
|
146
|
-
this.instance.config.processAfterIdentitySet =
|
|
147
|
-
options.processAfterIdentitySet;
|
|
148
|
-
} else {
|
|
149
|
-
this.instance.config.processAfterIdentitySet = false;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (options?.autoStartEnabled !== undefined) {
|
|
153
|
-
this.instance.config.autoStartEnabled = options.autoStartEnabled;
|
|
154
|
-
}
|
|
155
|
-
if (options?.themeMode) {
|
|
156
|
-
this.instance.config.themeMode = options.themeMode;
|
|
157
|
-
} else {
|
|
158
|
-
this.instance.config.themeMode = "light";
|
|
159
|
-
}
|
|
160
|
-
if (options?.language) {
|
|
161
|
-
this.instance.config.language = options.language;
|
|
162
|
-
} else {
|
|
163
|
-
this.instance.config.language = "en";
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (options?.customCssLink) {
|
|
167
|
-
this.instance.config.customCssLink = options.customCssLink;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (options?.setUser) {
|
|
171
|
-
this.instance.config.setUser = options.setUser;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (options?.onFormEvent) {
|
|
175
|
-
this.instance.config.onFormEvent = options.onFormEvent;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (options?.customProperties) {
|
|
179
|
-
this.instance.config.customProperties = options.customProperties;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
if (options?.onSessionDisabled) {
|
|
183
|
-
this.instance.config.onSessionDisabled = options.onSessionDisabled;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Mark as initialized
|
|
187
|
-
this.instance.initialized = true;
|
|
188
|
-
|
|
189
|
-
// Sync instance with window.encatch AFTER all config is set
|
|
190
|
-
// This ensures core-wrapper can access all properties
|
|
191
|
-
if (typeof window !== "undefined") {
|
|
192
|
-
window.encatch = this.instance;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Load core directly for module usage (after window.encatch is set)
|
|
196
|
-
loadCore();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Track a custom event
|
|
201
|
-
*/
|
|
202
|
-
trackEvent(eventName: string, properties?: Record<string, any>): void {
|
|
203
|
-
if (this.instance.trackEvent) {
|
|
204
|
-
this.instance.trackEvent(eventName, properties);
|
|
205
|
-
} else {
|
|
206
|
-
this.instance._i.push(["trackEvent", eventName, properties]);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Start the SDK session
|
|
212
|
-
*/
|
|
213
|
-
start(
|
|
214
|
-
userId?: string,
|
|
215
|
-
traits?: {
|
|
216
|
-
$set?: Record<string, any>;
|
|
217
|
-
$set_once?: Record<string, any>;
|
|
218
|
-
$counter?: Record<string, any>;
|
|
219
|
-
$unset?: string[];
|
|
220
|
-
[key: string]: any;
|
|
221
|
-
}
|
|
222
|
-
): void {
|
|
223
|
-
if (this.instance.start) {
|
|
224
|
-
this.instance.start(userId, traits);
|
|
225
|
-
} else {
|
|
226
|
-
this.instance._i.push(["start", userId, traits]);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Stop the SDK session
|
|
232
|
-
*/
|
|
233
|
-
stop(): void {
|
|
234
|
-
if (this.instance.stop) {
|
|
235
|
-
this.instance.stop();
|
|
236
|
-
} else {
|
|
237
|
-
this.instance._i.push(["stop"]);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Set or update user identity
|
|
243
|
-
*/
|
|
244
|
-
setUser(
|
|
245
|
-
userId?: string,
|
|
246
|
-
traits?: {
|
|
247
|
-
$set?: Record<string, any>;
|
|
248
|
-
$set_once?: Record<string, any>;
|
|
249
|
-
$counter?: Record<string, any>;
|
|
250
|
-
$unset?: string[];
|
|
251
|
-
[key: string]: any;
|
|
252
|
-
}
|
|
253
|
-
): void {
|
|
254
|
-
if (this.instance.setUser) {
|
|
255
|
-
this.instance.setUser(userId, traits);
|
|
256
|
-
} else {
|
|
257
|
-
this.instance._i.push(["setUser", userId, traits]);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* Set theme mode
|
|
263
|
-
*/
|
|
264
|
-
setThemeMode(theme: "light" | "dark"): void {
|
|
265
|
-
if (this.instance.setThemeMode) {
|
|
266
|
-
this.instance.setThemeMode(theme);
|
|
267
|
-
} else {
|
|
268
|
-
this.instance._i.push(["setThemeMode", theme]);
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Set language
|
|
274
|
-
*/
|
|
275
|
-
setLanguage(language: string): void {
|
|
276
|
-
if (this.instance.setLanguage) {
|
|
277
|
-
this.instance.setLanguage(language);
|
|
278
|
-
} else {
|
|
279
|
-
this.instance._i.push(["setLanguage", language]);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Set custom properties
|
|
285
|
-
*/
|
|
286
|
-
setCustomProperties(customProperties: Record<string, string>): void {
|
|
287
|
-
if (this.instance.setCustomProperties) {
|
|
288
|
-
this.instance.setCustomProperties(customProperties);
|
|
289
|
-
} else {
|
|
290
|
-
this.instance._i.push(["setCustomProperties", customProperties]);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Open feedback by configuration ID
|
|
296
|
-
*/
|
|
297
|
-
openFeedbackById(
|
|
298
|
-
feedbackConfigurationId: string,
|
|
299
|
-
theme?: "light" | "dark",
|
|
300
|
-
language?: string,
|
|
301
|
-
event?: string,
|
|
302
|
-
customProperties?: Record<string, string>,
|
|
303
|
-
prepopulatedAnswers?: any[]
|
|
304
|
-
): void {
|
|
305
|
-
if (this.instance.openFeedbackById) {
|
|
306
|
-
this.instance.openFeedbackById(
|
|
307
|
-
feedbackConfigurationId,
|
|
308
|
-
theme,
|
|
309
|
-
language,
|
|
310
|
-
event,
|
|
311
|
-
customProperties,
|
|
312
|
-
prepopulatedAnswers
|
|
313
|
-
);
|
|
314
|
-
} else {
|
|
315
|
-
this.instance._i.push([
|
|
316
|
-
"openFeedbackById",
|
|
317
|
-
feedbackConfigurationId,
|
|
318
|
-
theme,
|
|
319
|
-
language,
|
|
320
|
-
event,
|
|
321
|
-
customProperties,
|
|
322
|
-
prepopulatedAnswers,
|
|
323
|
-
]);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Open feedback by configuration name
|
|
329
|
-
*/
|
|
330
|
-
openFeedbackByName(
|
|
331
|
-
feedbackConfigurationName: string,
|
|
332
|
-
theme?: "light" | "dark",
|
|
333
|
-
language?: string,
|
|
334
|
-
event?: string,
|
|
335
|
-
customProperties?: Record<string, string>,
|
|
336
|
-
prepopulatedAnswers?: any[]
|
|
337
|
-
): void {
|
|
338
|
-
if (this.instance.openFeedbackByName) {
|
|
339
|
-
this.instance.openFeedbackByName(
|
|
340
|
-
feedbackConfigurationName,
|
|
341
|
-
theme,
|
|
342
|
-
language,
|
|
343
|
-
event,
|
|
344
|
-
customProperties,
|
|
345
|
-
prepopulatedAnswers
|
|
346
|
-
);
|
|
347
|
-
} else {
|
|
348
|
-
this.instance._i.push([
|
|
349
|
-
"openFeedbackByName",
|
|
350
|
-
feedbackConfigurationName,
|
|
351
|
-
theme,
|
|
352
|
-
language,
|
|
353
|
-
event,
|
|
354
|
-
customProperties,
|
|
355
|
-
prepopulatedAnswers,
|
|
356
|
-
]);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Verify which feedback IDs are eligible
|
|
362
|
-
*/
|
|
363
|
-
verifyFeedbackIds(feedbackConfigurationIds: string[]): string[] {
|
|
364
|
-
if (this.instance.verifyFeedbackIds) {
|
|
365
|
-
return this.instance.verifyFeedbackIds(feedbackConfigurationIds);
|
|
366
|
-
}
|
|
367
|
-
return [];
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
/**
|
|
371
|
-
* Force fetch eligible feedbacks
|
|
372
|
-
*/
|
|
373
|
-
async forceFetchEligibleFeedbacks(): Promise<void> {
|
|
374
|
-
if (this.instance.forceFetchEligibleFeedbacks) {
|
|
375
|
-
return this.instance.forceFetchEligibleFeedbacks();
|
|
376
|
-
}
|
|
377
|
-
return Promise.resolve();
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Capture page scroll event
|
|
382
|
-
*/
|
|
383
|
-
capturePageScrollEvent(scrollPercent: string): void {
|
|
384
|
-
if (this.instance.capturePageScrollEvent) {
|
|
385
|
-
this.instance.capturePageScrollEvent(scrollPercent);
|
|
386
|
-
} else {
|
|
387
|
-
this.instance._i.push(["capturePageScrollEvent", scrollPercent]);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Subscribe to form events
|
|
393
|
-
*/
|
|
394
|
-
on<T extends FormEventType>(
|
|
395
|
-
eventType: T,
|
|
396
|
-
callback: (payload: FormEventPayload[T]) => void
|
|
397
|
-
): () => void {
|
|
398
|
-
if (this.instance.on) {
|
|
399
|
-
return this.instance.on(eventType, callback);
|
|
400
|
-
}
|
|
401
|
-
// Fallback to queue
|
|
402
|
-
const subscription = { eventType, callback };
|
|
403
|
-
this.instance._eventSubscriptions = this.instance._eventSubscriptions || [];
|
|
404
|
-
this.instance._eventSubscriptions.push(subscription);
|
|
405
|
-
return () => {
|
|
406
|
-
const index = this.instance._eventSubscriptions?.indexOf(subscription);
|
|
407
|
-
if (index !== undefined && index > -1) {
|
|
408
|
-
this.instance._eventSubscriptions?.splice(index, 1);
|
|
409
|
-
}
|
|
410
|
-
};
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
/**
|
|
414
|
-
* Get the internal instance (for advanced usage)
|
|
415
|
-
*/
|
|
416
|
-
getInstance(): EncatchGlobal {
|
|
417
|
-
return this.instance;
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Export a default instance for convenience (SSR-safe)
|
|
422
|
-
export const encatch = typeof window !== "undefined" ? new Encatch() : (null as any);
|
|
423
|
-
|
|
424
|
-
// Export types
|
|
425
|
-
export type { EncatchConfig, OnFormEventHandler, FormEventBuilder } from "./@types/encatch-type";
|
|
426
|
-
|
|
427
|
-
// Encatch class is already exported above with "export class Encatch"
|
|
428
|
-
|