@perspective-ai/sdk 1.0.1 → 1.1.2
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/browser.cjs +107 -31
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +13 -0
- package/dist/browser.d.ts +13 -0
- package/dist/browser.js +107 -31
- package/dist/browser.js.map +1 -1
- package/dist/cdn/perspective.global.js +17 -17
- package/dist/cdn/perspective.global.js.map +1 -1
- package/dist/constants.cjs +8 -23
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +5 -4
- package/dist/constants.d.ts +5 -4
- package/dist/constants.js +9 -23
- package/dist/constants.js.map +1 -1
- package/dist/index.cjs +86 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -1
- package/dist/index.d.ts +60 -1
- package/dist/index.js +82 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/browser.ts +42 -3
- package/src/constants.ts +7 -28
- package/src/iframe.test.ts +115 -0
- package/src/iframe.ts +8 -9
- package/src/index.ts +13 -0
- package/src/triggers.test.ts +272 -0
- package/src/triggers.ts +127 -0
- package/src/types.ts +19 -0
package/dist/browser.cjs
CHANGED
|
@@ -38,7 +38,7 @@ __export(browser_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(browser_exports);
|
|
39
39
|
|
|
40
40
|
// src/constants.ts
|
|
41
|
-
var SDK_VERSION = "1.
|
|
41
|
+
var SDK_VERSION = "1.1.2";
|
|
42
42
|
var FEATURES = {
|
|
43
43
|
RESIZE: 1 << 0,
|
|
44
44
|
// 0b0001
|
|
@@ -67,26 +67,9 @@ var BRAND_KEYS = {
|
|
|
67
67
|
darkBg: "brand.dark.bg",
|
|
68
68
|
darkText: "brand.dark.text"
|
|
69
69
|
};
|
|
70
|
-
var UTM_PARAMS = [
|
|
71
|
-
"utm_source",
|
|
72
|
-
"utm_medium",
|
|
73
|
-
"utm_campaign",
|
|
74
|
-
"utm_term",
|
|
75
|
-
"utm_content"
|
|
76
|
-
];
|
|
77
70
|
var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
78
|
-
PARAM_KEYS
|
|
79
|
-
|
|
80
|
-
PARAM_KEYS.theme,
|
|
81
|
-
BRAND_KEYS.primary,
|
|
82
|
-
BRAND_KEYS.secondary,
|
|
83
|
-
BRAND_KEYS.bg,
|
|
84
|
-
BRAND_KEYS.text,
|
|
85
|
-
BRAND_KEYS.darkPrimary,
|
|
86
|
-
BRAND_KEYS.darkSecondary,
|
|
87
|
-
BRAND_KEYS.darkBg,
|
|
88
|
-
BRAND_KEYS.darkText,
|
|
89
|
-
...UTM_PARAMS
|
|
71
|
+
...Object.values(PARAM_KEYS),
|
|
72
|
+
...Object.values(BRAND_KEYS)
|
|
90
73
|
]);
|
|
91
74
|
var DATA_ATTRS = {
|
|
92
75
|
widget: "data-perspective-widget",
|
|
@@ -101,7 +84,9 @@ var DATA_ATTRS = {
|
|
|
101
84
|
brand: "data-perspective-brand",
|
|
102
85
|
brandDark: "data-perspective-brand-dark",
|
|
103
86
|
theme: "data-perspective-theme",
|
|
104
|
-
noStyle: "data-perspective-no-style"
|
|
87
|
+
noStyle: "data-perspective-no-style",
|
|
88
|
+
autoOpen: "data-perspective-auto-open",
|
|
89
|
+
showOnce: "data-perspective-show-once"
|
|
105
90
|
};
|
|
106
91
|
var MESSAGE_TYPES = {
|
|
107
92
|
// SDK -> Iframe (initialization)
|
|
@@ -135,9 +120,78 @@ var THEME_VALUES = {
|
|
|
135
120
|
system: "system"
|
|
136
121
|
};
|
|
137
122
|
var STORAGE_KEYS = {
|
|
138
|
-
anonId: "perspective-anon-id"
|
|
123
|
+
anonId: "perspective-anon-id",
|
|
124
|
+
triggerShown: "perspective-trigger-shown"
|
|
139
125
|
};
|
|
140
126
|
|
|
127
|
+
// src/triggers.ts
|
|
128
|
+
function parseTriggerAttr(value) {
|
|
129
|
+
const trimmed = value.trim();
|
|
130
|
+
if (trimmed.startsWith("timeout:")) {
|
|
131
|
+
const delay = parseInt(trimmed.slice("timeout:".length), 10);
|
|
132
|
+
if (isNaN(delay) || delay < 0) {
|
|
133
|
+
throw new Error(`Invalid timeout delay: "${value}"`);
|
|
134
|
+
}
|
|
135
|
+
return { type: "timeout", delay };
|
|
136
|
+
}
|
|
137
|
+
if (trimmed === "timeout") {
|
|
138
|
+
return { type: "timeout", delay: 5e3 };
|
|
139
|
+
}
|
|
140
|
+
if (trimmed === "exit-intent") {
|
|
141
|
+
return { type: "exit-intent" };
|
|
142
|
+
}
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Unknown trigger type: "${value}". Expected "timeout:<ms>" or "exit-intent".`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function setupTrigger(config, callback) {
|
|
148
|
+
if (config.type === "timeout") {
|
|
149
|
+
const timer = setTimeout(callback, config.delay);
|
|
150
|
+
return () => clearTimeout(timer);
|
|
151
|
+
}
|
|
152
|
+
if (config.type === "exit-intent") {
|
|
153
|
+
const handler = (e) => {
|
|
154
|
+
if (e.clientY <= 0) {
|
|
155
|
+
callback();
|
|
156
|
+
document.removeEventListener("mouseleave", handler);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
document.addEventListener("mouseleave", handler);
|
|
160
|
+
return () => document.removeEventListener("mouseleave", handler);
|
|
161
|
+
}
|
|
162
|
+
const _exhaustive = config;
|
|
163
|
+
throw new Error(
|
|
164
|
+
`Unknown trigger type: ${_exhaustive.type}`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
function storageKey(researchId) {
|
|
168
|
+
return `${STORAGE_KEYS.triggerShown}:${researchId}`;
|
|
169
|
+
}
|
|
170
|
+
function parseShowOnceAttr(value) {
|
|
171
|
+
if (!value) return "session";
|
|
172
|
+
const trimmed = value.trim();
|
|
173
|
+
if (trimmed === "visitor") return "visitor";
|
|
174
|
+
if (trimmed === "false") return false;
|
|
175
|
+
return "session";
|
|
176
|
+
}
|
|
177
|
+
function shouldShow(researchId, showOnce) {
|
|
178
|
+
if (showOnce === false) return true;
|
|
179
|
+
try {
|
|
180
|
+
const storage = showOnce === "visitor" ? localStorage : sessionStorage;
|
|
181
|
+
return storage.getItem(storageKey(researchId)) === null;
|
|
182
|
+
} catch {
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function markShown(researchId, showOnce) {
|
|
187
|
+
if (showOnce === false) return;
|
|
188
|
+
try {
|
|
189
|
+
const storage = showOnce === "visitor" ? localStorage : sessionStorage;
|
|
190
|
+
storage.setItem(storageKey(researchId), "1");
|
|
191
|
+
} catch {
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
141
195
|
// src/config.ts
|
|
142
196
|
var DEFAULT_HOST = "https://getperspective.ai";
|
|
143
197
|
var globalConfig = {};
|
|
@@ -262,13 +316,12 @@ function getOrCreateAnonId() {
|
|
|
262
316
|
return crypto.randomUUID();
|
|
263
317
|
}
|
|
264
318
|
}
|
|
265
|
-
function
|
|
319
|
+
function getParentSearchParams() {
|
|
266
320
|
if (!hasDom()) return {};
|
|
267
321
|
const params = {};
|
|
268
322
|
const searchParams = new URLSearchParams(window.location.search);
|
|
269
|
-
for (const key of
|
|
270
|
-
|
|
271
|
-
if (value) {
|
|
323
|
+
for (const [key, value] of searchParams.entries()) {
|
|
324
|
+
if (!RESERVED_PARAMS.has(key)) {
|
|
272
325
|
params[key] = value;
|
|
273
326
|
}
|
|
274
327
|
}
|
|
@@ -291,8 +344,8 @@ function buildIframeUrl(researchId, type, host, customParams, brand, themeOverri
|
|
|
291
344
|
} else {
|
|
292
345
|
url.searchParams.set(PARAM_KEYS.theme, themeOverride || THEME_VALUES.light);
|
|
293
346
|
}
|
|
294
|
-
const
|
|
295
|
-
for (const [key, value] of Object.entries(
|
|
347
|
+
const parentParams = getParentSearchParams();
|
|
348
|
+
for (const [key, value] of Object.entries(parentParams)) {
|
|
296
349
|
url.searchParams.set(key, value);
|
|
297
350
|
}
|
|
298
351
|
const setColor = (key, color) => {
|
|
@@ -1616,6 +1669,7 @@ function createFullpage(config) {
|
|
|
1616
1669
|
|
|
1617
1670
|
// src/browser.ts
|
|
1618
1671
|
var instances = /* @__PURE__ */ new Map();
|
|
1672
|
+
var triggerCleanups = /* @__PURE__ */ new Map();
|
|
1619
1673
|
var configCache = /* @__PURE__ */ new Map();
|
|
1620
1674
|
var styledButtons = /* @__PURE__ */ new Map();
|
|
1621
1675
|
var buttonThemeMediaQuery = null;
|
|
@@ -1795,6 +1849,8 @@ function destroy(researchId) {
|
|
|
1795
1849
|
function destroyAll() {
|
|
1796
1850
|
instances.forEach((instance) => instance.unmount());
|
|
1797
1851
|
instances.clear();
|
|
1852
|
+
triggerCleanups.forEach((cleanup) => cleanup());
|
|
1853
|
+
triggerCleanups.clear();
|
|
1798
1854
|
styledButtons.clear();
|
|
1799
1855
|
teardownButtonThemeListener();
|
|
1800
1856
|
}
|
|
@@ -1821,9 +1877,29 @@ function autoInit() {
|
|
|
1821
1877
|
if (el.hasAttribute("data-perspective-initialized")) return;
|
|
1822
1878
|
el.setAttribute("data-perspective-initialized", "true");
|
|
1823
1879
|
const researchId = el.getAttribute(DATA_ATTRS.popup);
|
|
1824
|
-
if (researchId)
|
|
1825
|
-
|
|
1826
|
-
|
|
1880
|
+
if (!researchId) return;
|
|
1881
|
+
const params = parseParamsAttr(el);
|
|
1882
|
+
const brandConfig = extractBrandConfig(el);
|
|
1883
|
+
const autoOpenAttr = el.getAttribute(DATA_ATTRS.autoOpen);
|
|
1884
|
+
if (autoOpenAttr) {
|
|
1885
|
+
try {
|
|
1886
|
+
const trigger = parseTriggerAttr(autoOpenAttr);
|
|
1887
|
+
const showOnce = parseShowOnceAttr(
|
|
1888
|
+
el.getAttribute(DATA_ATTRS.showOnce)
|
|
1889
|
+
);
|
|
1890
|
+
if (shouldShow(researchId, showOnce)) {
|
|
1891
|
+
triggerCleanups.get(researchId)?.();
|
|
1892
|
+
const cleanup = setupTrigger(trigger, () => {
|
|
1893
|
+
triggerCleanups.delete(researchId);
|
|
1894
|
+
markShown(researchId, showOnce);
|
|
1895
|
+
init({ researchId, type: "popup", params, ...brandConfig });
|
|
1896
|
+
});
|
|
1897
|
+
triggerCleanups.set(researchId, cleanup);
|
|
1898
|
+
}
|
|
1899
|
+
} catch (e) {
|
|
1900
|
+
console.warn("[Perspective]", e.message);
|
|
1901
|
+
}
|
|
1902
|
+
} else {
|
|
1827
1903
|
styleButton(el, DEFAULT_THEME, brandConfig);
|
|
1828
1904
|
el.addEventListener("click", (e) => {
|
|
1829
1905
|
e.preventDefault();
|