@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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
|
-
var SDK_VERSION = "1.
|
|
2
|
+
var SDK_VERSION = "1.1.2";
|
|
3
3
|
var FEATURES = {
|
|
4
4
|
RESIZE: 1 << 0,
|
|
5
5
|
// 0b0001
|
|
@@ -28,26 +28,9 @@ var BRAND_KEYS = {
|
|
|
28
28
|
darkBg: "brand.dark.bg",
|
|
29
29
|
darkText: "brand.dark.text"
|
|
30
30
|
};
|
|
31
|
-
var UTM_PARAMS = [
|
|
32
|
-
"utm_source",
|
|
33
|
-
"utm_medium",
|
|
34
|
-
"utm_campaign",
|
|
35
|
-
"utm_term",
|
|
36
|
-
"utm_content"
|
|
37
|
-
];
|
|
38
31
|
var RESERVED_PARAMS = /* @__PURE__ */ new Set([
|
|
39
|
-
PARAM_KEYS
|
|
40
|
-
|
|
41
|
-
PARAM_KEYS.theme,
|
|
42
|
-
BRAND_KEYS.primary,
|
|
43
|
-
BRAND_KEYS.secondary,
|
|
44
|
-
BRAND_KEYS.bg,
|
|
45
|
-
BRAND_KEYS.text,
|
|
46
|
-
BRAND_KEYS.darkPrimary,
|
|
47
|
-
BRAND_KEYS.darkSecondary,
|
|
48
|
-
BRAND_KEYS.darkBg,
|
|
49
|
-
BRAND_KEYS.darkText,
|
|
50
|
-
...UTM_PARAMS
|
|
32
|
+
...Object.values(PARAM_KEYS),
|
|
33
|
+
...Object.values(BRAND_KEYS)
|
|
51
34
|
]);
|
|
52
35
|
var DATA_ATTRS = {
|
|
53
36
|
widget: "data-perspective-widget",
|
|
@@ -62,7 +45,9 @@ var DATA_ATTRS = {
|
|
|
62
45
|
brand: "data-perspective-brand",
|
|
63
46
|
brandDark: "data-perspective-brand-dark",
|
|
64
47
|
theme: "data-perspective-theme",
|
|
65
|
-
noStyle: "data-perspective-no-style"
|
|
48
|
+
noStyle: "data-perspective-no-style",
|
|
49
|
+
autoOpen: "data-perspective-auto-open",
|
|
50
|
+
showOnce: "data-perspective-show-once"
|
|
66
51
|
};
|
|
67
52
|
var MESSAGE_TYPES = {
|
|
68
53
|
// SDK -> Iframe (initialization)
|
|
@@ -96,9 +81,78 @@ var THEME_VALUES = {
|
|
|
96
81
|
system: "system"
|
|
97
82
|
};
|
|
98
83
|
var STORAGE_KEYS = {
|
|
99
|
-
anonId: "perspective-anon-id"
|
|
84
|
+
anonId: "perspective-anon-id",
|
|
85
|
+
triggerShown: "perspective-trigger-shown"
|
|
100
86
|
};
|
|
101
87
|
|
|
88
|
+
// src/triggers.ts
|
|
89
|
+
function parseTriggerAttr(value) {
|
|
90
|
+
const trimmed = value.trim();
|
|
91
|
+
if (trimmed.startsWith("timeout:")) {
|
|
92
|
+
const delay = parseInt(trimmed.slice("timeout:".length), 10);
|
|
93
|
+
if (isNaN(delay) || delay < 0) {
|
|
94
|
+
throw new Error(`Invalid timeout delay: "${value}"`);
|
|
95
|
+
}
|
|
96
|
+
return { type: "timeout", delay };
|
|
97
|
+
}
|
|
98
|
+
if (trimmed === "timeout") {
|
|
99
|
+
return { type: "timeout", delay: 5e3 };
|
|
100
|
+
}
|
|
101
|
+
if (trimmed === "exit-intent") {
|
|
102
|
+
return { type: "exit-intent" };
|
|
103
|
+
}
|
|
104
|
+
throw new Error(
|
|
105
|
+
`Unknown trigger type: "${value}". Expected "timeout:<ms>" or "exit-intent".`
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
function setupTrigger(config, callback) {
|
|
109
|
+
if (config.type === "timeout") {
|
|
110
|
+
const timer = setTimeout(callback, config.delay);
|
|
111
|
+
return () => clearTimeout(timer);
|
|
112
|
+
}
|
|
113
|
+
if (config.type === "exit-intent") {
|
|
114
|
+
const handler = (e) => {
|
|
115
|
+
if (e.clientY <= 0) {
|
|
116
|
+
callback();
|
|
117
|
+
document.removeEventListener("mouseleave", handler);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
document.addEventListener("mouseleave", handler);
|
|
121
|
+
return () => document.removeEventListener("mouseleave", handler);
|
|
122
|
+
}
|
|
123
|
+
const _exhaustive = config;
|
|
124
|
+
throw new Error(
|
|
125
|
+
`Unknown trigger type: ${_exhaustive.type}`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
function storageKey(researchId) {
|
|
129
|
+
return `${STORAGE_KEYS.triggerShown}:${researchId}`;
|
|
130
|
+
}
|
|
131
|
+
function parseShowOnceAttr(value) {
|
|
132
|
+
if (!value) return "session";
|
|
133
|
+
const trimmed = value.trim();
|
|
134
|
+
if (trimmed === "visitor") return "visitor";
|
|
135
|
+
if (trimmed === "false") return false;
|
|
136
|
+
return "session";
|
|
137
|
+
}
|
|
138
|
+
function shouldShow(researchId, showOnce) {
|
|
139
|
+
if (showOnce === false) return true;
|
|
140
|
+
try {
|
|
141
|
+
const storage = showOnce === "visitor" ? localStorage : sessionStorage;
|
|
142
|
+
return storage.getItem(storageKey(researchId)) === null;
|
|
143
|
+
} catch {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function markShown(researchId, showOnce) {
|
|
148
|
+
if (showOnce === false) return;
|
|
149
|
+
try {
|
|
150
|
+
const storage = showOnce === "visitor" ? localStorage : sessionStorage;
|
|
151
|
+
storage.setItem(storageKey(researchId), "1");
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
102
156
|
// src/config.ts
|
|
103
157
|
var DEFAULT_HOST = "https://getperspective.ai";
|
|
104
158
|
var globalConfig = {};
|
|
@@ -223,13 +277,12 @@ function getOrCreateAnonId() {
|
|
|
223
277
|
return crypto.randomUUID();
|
|
224
278
|
}
|
|
225
279
|
}
|
|
226
|
-
function
|
|
280
|
+
function getParentSearchParams() {
|
|
227
281
|
if (!hasDom()) return {};
|
|
228
282
|
const params = {};
|
|
229
283
|
const searchParams = new URLSearchParams(window.location.search);
|
|
230
|
-
for (const key of
|
|
231
|
-
|
|
232
|
-
if (value) {
|
|
284
|
+
for (const [key, value] of searchParams.entries()) {
|
|
285
|
+
if (!RESERVED_PARAMS.has(key)) {
|
|
233
286
|
params[key] = value;
|
|
234
287
|
}
|
|
235
288
|
}
|
|
@@ -252,8 +305,8 @@ function buildIframeUrl(researchId, type, host, customParams, brand, themeOverri
|
|
|
252
305
|
} else {
|
|
253
306
|
url.searchParams.set(PARAM_KEYS.theme, themeOverride || THEME_VALUES.light);
|
|
254
307
|
}
|
|
255
|
-
const
|
|
256
|
-
for (const [key, value] of Object.entries(
|
|
308
|
+
const parentParams = getParentSearchParams();
|
|
309
|
+
for (const [key, value] of Object.entries(parentParams)) {
|
|
257
310
|
url.searchParams.set(key, value);
|
|
258
311
|
}
|
|
259
312
|
const setColor = (key, color) => {
|
|
@@ -1577,6 +1630,7 @@ function createFullpage(config) {
|
|
|
1577
1630
|
|
|
1578
1631
|
// src/browser.ts
|
|
1579
1632
|
var instances = /* @__PURE__ */ new Map();
|
|
1633
|
+
var triggerCleanups = /* @__PURE__ */ new Map();
|
|
1580
1634
|
var configCache = /* @__PURE__ */ new Map();
|
|
1581
1635
|
var styledButtons = /* @__PURE__ */ new Map();
|
|
1582
1636
|
var buttonThemeMediaQuery = null;
|
|
@@ -1756,6 +1810,8 @@ function destroy(researchId) {
|
|
|
1756
1810
|
function destroyAll() {
|
|
1757
1811
|
instances.forEach((instance) => instance.unmount());
|
|
1758
1812
|
instances.clear();
|
|
1813
|
+
triggerCleanups.forEach((cleanup) => cleanup());
|
|
1814
|
+
triggerCleanups.clear();
|
|
1759
1815
|
styledButtons.clear();
|
|
1760
1816
|
teardownButtonThemeListener();
|
|
1761
1817
|
}
|
|
@@ -1782,9 +1838,29 @@ function autoInit() {
|
|
|
1782
1838
|
if (el.hasAttribute("data-perspective-initialized")) return;
|
|
1783
1839
|
el.setAttribute("data-perspective-initialized", "true");
|
|
1784
1840
|
const researchId = el.getAttribute(DATA_ATTRS.popup);
|
|
1785
|
-
if (researchId)
|
|
1786
|
-
|
|
1787
|
-
|
|
1841
|
+
if (!researchId) return;
|
|
1842
|
+
const params = parseParamsAttr(el);
|
|
1843
|
+
const brandConfig = extractBrandConfig(el);
|
|
1844
|
+
const autoOpenAttr = el.getAttribute(DATA_ATTRS.autoOpen);
|
|
1845
|
+
if (autoOpenAttr) {
|
|
1846
|
+
try {
|
|
1847
|
+
const trigger = parseTriggerAttr(autoOpenAttr);
|
|
1848
|
+
const showOnce = parseShowOnceAttr(
|
|
1849
|
+
el.getAttribute(DATA_ATTRS.showOnce)
|
|
1850
|
+
);
|
|
1851
|
+
if (shouldShow(researchId, showOnce)) {
|
|
1852
|
+
triggerCleanups.get(researchId)?.();
|
|
1853
|
+
const cleanup = setupTrigger(trigger, () => {
|
|
1854
|
+
triggerCleanups.delete(researchId);
|
|
1855
|
+
markShown(researchId, showOnce);
|
|
1856
|
+
init({ researchId, type: "popup", params, ...brandConfig });
|
|
1857
|
+
});
|
|
1858
|
+
triggerCleanups.set(researchId, cleanup);
|
|
1859
|
+
}
|
|
1860
|
+
} catch (e) {
|
|
1861
|
+
console.warn("[Perspective]", e.message);
|
|
1862
|
+
}
|
|
1863
|
+
} else {
|
|
1788
1864
|
styleButton(el, DEFAULT_THEME, brandConfig);
|
|
1789
1865
|
el.addEventListener("click", (e) => {
|
|
1790
1866
|
e.preventDefault();
|