@magicfeedback/popup-sdk 1.0.10 → 1.0.12
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 +269 -204
- package/dist/index.d.mts +56 -18
- package/dist/index.d.ts +56 -18
- package/dist/index.js +574 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +574 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1712,6 +1712,13 @@ var require_magicfeedback_sdk_browser = __commonJS({
|
|
|
1712
1712
|
}
|
|
1713
1713
|
});
|
|
1714
1714
|
|
|
1715
|
+
// src/types/index.ts
|
|
1716
|
+
var POPUP_TRIGGER_CONDITION_STATUSES = [
|
|
1717
|
+
"SHOWED",
|
|
1718
|
+
"PARTIAL",
|
|
1719
|
+
"COMPLETED"
|
|
1720
|
+
];
|
|
1721
|
+
|
|
1715
1722
|
// src/ui/renderPopup.ts
|
|
1716
1723
|
var import_native = __toESM(require_magicfeedback_sdk_browser());
|
|
1717
1724
|
function ensureMagicFeedbackStyles(popup) {
|
|
@@ -1774,7 +1781,7 @@ function ensureResponsiveStyles(popup) {
|
|
|
1774
1781
|
`;
|
|
1775
1782
|
popup.appendChild(style);
|
|
1776
1783
|
}
|
|
1777
|
-
async function renderPopup(container, surveyId, productId, actions, emit, onClose) {
|
|
1784
|
+
async function renderPopup(container, surveyId, productId, actions, emit, onClose, env = "production") {
|
|
1778
1785
|
let surveyCompletedEmitted = false;
|
|
1779
1786
|
let stylesInjected = false;
|
|
1780
1787
|
const popup = document.createElement("div");
|
|
@@ -2058,7 +2065,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2058
2065
|
setLoading(false);
|
|
2059
2066
|
return;
|
|
2060
2067
|
}
|
|
2061
|
-
import_native.default.init({ debug: true, env: "prod" });
|
|
2068
|
+
import_native.default.init({ debug: true, env: env === "production" ? "prod" : "dev" });
|
|
2062
2069
|
formInstance = import_native.default.form(surveyId, productId);
|
|
2063
2070
|
const generateOptions = {
|
|
2064
2071
|
addButton: false,
|
|
@@ -2173,6 +2180,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2173
2180
|
updateButtons("completed");
|
|
2174
2181
|
return;
|
|
2175
2182
|
}
|
|
2183
|
+
emit("popup_clicked", surveyId, { action: "partial" });
|
|
2176
2184
|
if (total > 1 && progress > 0 && progress < total) {
|
|
2177
2185
|
updateButtons("in_progress_next");
|
|
2178
2186
|
} else {
|
|
@@ -2209,12 +2217,18 @@ function setupTrigger(popups, trigger) {
|
|
|
2209
2217
|
case "exit":
|
|
2210
2218
|
setupExitTrigger(popups, trigger);
|
|
2211
2219
|
break;
|
|
2220
|
+
case "event":
|
|
2221
|
+
setupEventTrigger(popups, trigger);
|
|
2222
|
+
break;
|
|
2223
|
+
case "click":
|
|
2224
|
+
setupClickTrigger(popups, trigger);
|
|
2225
|
+
break;
|
|
2212
2226
|
}
|
|
2213
2227
|
}
|
|
2214
2228
|
function setupTimeTrigger(popups, trigger) {
|
|
2215
2229
|
const delay = trigger.value || 5e3;
|
|
2216
2230
|
setTimeout(() => {
|
|
2217
|
-
popups.triggerSurvey(trigger.surveyId);
|
|
2231
|
+
popups.triggerSurvey(trigger.surveyId, trigger.popupId);
|
|
2218
2232
|
}, delay);
|
|
2219
2233
|
popups.debug(`Time trigger set for ${delay}ms`);
|
|
2220
2234
|
}
|
|
@@ -2223,7 +2237,7 @@ function setupScrollTrigger(popups, trigger) {
|
|
|
2223
2237
|
const handler = () => {
|
|
2224
2238
|
const scrollPercentage = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight) * 100;
|
|
2225
2239
|
if (scrollPercentage >= threshold) {
|
|
2226
|
-
popups.triggerSurvey(trigger.surveyId);
|
|
2240
|
+
popups.triggerSurvey(trigger.surveyId, trigger.popupId);
|
|
2227
2241
|
window.removeEventListener("scroll", handler);
|
|
2228
2242
|
}
|
|
2229
2243
|
};
|
|
@@ -2231,23 +2245,137 @@ function setupScrollTrigger(popups, trigger) {
|
|
|
2231
2245
|
popups.debug(`Scroll trigger set for ${threshold}%`);
|
|
2232
2246
|
}
|
|
2233
2247
|
function setupExitTrigger(popups, trigger) {
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2248
|
+
if (typeof window === "undefined") return;
|
|
2249
|
+
const delaySeconds = parseExitDelaySeconds(trigger.value);
|
|
2250
|
+
const historyRef = window.history;
|
|
2251
|
+
const originalPushState = historyRef.pushState.bind(historyRef);
|
|
2252
|
+
const originalReplaceState = historyRef.replaceState.bind(historyRef);
|
|
2253
|
+
let lastUrl = normalizeUrl(window.location.href);
|
|
2254
|
+
let lastQueuedKey = "";
|
|
2255
|
+
let lastQueuedAt = 0;
|
|
2256
|
+
const queueLeave = (fromRaw, toRaw) => {
|
|
2257
|
+
const from = normalizeUrl(fromRaw);
|
|
2258
|
+
const to = normalizeUrl(toRaw);
|
|
2259
|
+
if (!from || !to || from === to) return;
|
|
2260
|
+
const key = `${from}=>${to}`;
|
|
2261
|
+
const now = Date.now();
|
|
2262
|
+
if (key === lastQueuedKey && now - lastQueuedAt < 150) return;
|
|
2263
|
+
lastQueuedKey = key;
|
|
2264
|
+
lastQueuedAt = now;
|
|
2265
|
+
popups.queueExitPopup(trigger.surveyId, delaySeconds, from, trigger.popupId);
|
|
2266
|
+
};
|
|
2267
|
+
const handleNavigation = (to) => {
|
|
2268
|
+
const from = lastUrl;
|
|
2269
|
+
queueLeave(from, to);
|
|
2270
|
+
lastUrl = normalizeUrl(to);
|
|
2271
|
+
};
|
|
2272
|
+
const handleDocumentClick = (event) => {
|
|
2273
|
+
if (event.defaultPrevented) return;
|
|
2274
|
+
if (event.button !== 0) return;
|
|
2275
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
|
|
2276
|
+
const anchor = event.target?.closest?.("a");
|
|
2277
|
+
if (!(anchor instanceof HTMLAnchorElement)) return;
|
|
2278
|
+
const href = anchor.getAttribute("href");
|
|
2279
|
+
if (!href || href.startsWith("javascript:") || href.startsWith("mailto:") || href.startsWith("tel:")) {
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
const target = anchor.getAttribute("target");
|
|
2283
|
+
if (target && target !== "_self") return;
|
|
2284
|
+
let destination;
|
|
2285
|
+
try {
|
|
2286
|
+
destination = new URL(href, window.location.href);
|
|
2287
|
+
} catch {
|
|
2288
|
+
return;
|
|
2238
2289
|
}
|
|
2290
|
+
if (destination.origin !== window.location.origin) return;
|
|
2291
|
+
queueLeave(window.location.href, destination.href);
|
|
2292
|
+
};
|
|
2293
|
+
const handleHashChange = (event) => {
|
|
2294
|
+
const to = event.newURL || window.location.href;
|
|
2295
|
+
const from = event.oldURL || lastUrl;
|
|
2296
|
+
queueLeave(from, to);
|
|
2297
|
+
lastUrl = normalizeUrl(to);
|
|
2239
2298
|
};
|
|
2240
|
-
|
|
2241
|
-
|
|
2299
|
+
const handlePopState = () => {
|
|
2300
|
+
handleNavigation(window.location.href);
|
|
2301
|
+
};
|
|
2302
|
+
historyRef.pushState = function(data, unused, url) {
|
|
2303
|
+
const from = window.location.href;
|
|
2304
|
+
const result = originalPushState(data, unused, url);
|
|
2305
|
+
queueLeave(from, window.location.href);
|
|
2306
|
+
lastUrl = normalizeUrl(window.location.href);
|
|
2307
|
+
return result;
|
|
2308
|
+
};
|
|
2309
|
+
historyRef.replaceState = function(data, unused, url) {
|
|
2310
|
+
const from = window.location.href;
|
|
2311
|
+
const result = originalReplaceState(data, unused, url);
|
|
2312
|
+
queueLeave(from, window.location.href);
|
|
2313
|
+
lastUrl = normalizeUrl(window.location.href);
|
|
2314
|
+
return result;
|
|
2315
|
+
};
|
|
2316
|
+
document.addEventListener("click", handleDocumentClick, true);
|
|
2317
|
+
window.addEventListener("hashchange", handleHashChange);
|
|
2318
|
+
window.addEventListener("popstate", handlePopState);
|
|
2319
|
+
popups.debug("Exit trigger set (deferred to next route)", {
|
|
2320
|
+
surveyId: trigger.surveyId,
|
|
2321
|
+
delaySeconds
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
function setupEventTrigger(popups, trigger) {
|
|
2325
|
+
popups.debug("Event trigger registered", {
|
|
2326
|
+
popupId: trigger.popupId,
|
|
2327
|
+
surveyId: trigger.surveyId,
|
|
2328
|
+
eventName: String(trigger.value || "")
|
|
2329
|
+
});
|
|
2330
|
+
}
|
|
2331
|
+
function parseExitDelaySeconds(value) {
|
|
2332
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
2333
|
+
return Math.max(0, value);
|
|
2334
|
+
}
|
|
2335
|
+
if (typeof value === "string" && value.trim()) {
|
|
2336
|
+
const parsed = Number(value);
|
|
2337
|
+
if (Number.isFinite(parsed)) return Math.max(0, parsed);
|
|
2338
|
+
}
|
|
2339
|
+
return 0;
|
|
2340
|
+
}
|
|
2341
|
+
function normalizeUrl(value) {
|
|
2342
|
+
if (!value) return "";
|
|
2343
|
+
const withoutIndex = value.replace(/\/index\.html(?=($|[?#]))/i, "");
|
|
2344
|
+
return withoutIndex.length > 1 && withoutIndex.endsWith("/") ? withoutIndex.slice(0, -1) : withoutIndex;
|
|
2345
|
+
}
|
|
2346
|
+
function setupClickTrigger(popups, trigger) {
|
|
2347
|
+
const targetId = typeof trigger.value === "string" ? trigger.value : "";
|
|
2348
|
+
if (!targetId) {
|
|
2349
|
+
popups.debug("Click trigger missing element id", trigger);
|
|
2350
|
+
return;
|
|
2351
|
+
}
|
|
2352
|
+
const attach = () => {
|
|
2353
|
+
const el = document.getElementById(targetId);
|
|
2354
|
+
if (!el) {
|
|
2355
|
+
popups.debug("Click trigger target not found", targetId);
|
|
2356
|
+
return false;
|
|
2357
|
+
}
|
|
2358
|
+
const handler = (e) => {
|
|
2359
|
+
if (e.defaultPrevented) return;
|
|
2360
|
+
popups.triggerSurvey(trigger.surveyId, trigger.popupId);
|
|
2361
|
+
el.removeEventListener("click", handler);
|
|
2362
|
+
};
|
|
2363
|
+
el.addEventListener("click", handler);
|
|
2364
|
+
popups.debug(`Click trigger set for #${targetId}`);
|
|
2365
|
+
return true;
|
|
2366
|
+
};
|
|
2367
|
+
if (typeof document === "undefined") return;
|
|
2368
|
+
if (attach()) return;
|
|
2369
|
+
window.addEventListener("DOMContentLoaded", () => attach(), { once: true });
|
|
2242
2370
|
}
|
|
2243
2371
|
|
|
2244
2372
|
// src/config/env.ts
|
|
2245
2373
|
var ENVIRONMENT_MAP = {
|
|
2246
2374
|
development: {
|
|
2247
|
-
apiBaseUrl: "https://api-dev.
|
|
2375
|
+
apiBaseUrl: "https://api-dev.deepdots.com"
|
|
2248
2376
|
},
|
|
2249
2377
|
production: {
|
|
2250
|
-
apiBaseUrl: "https://api.
|
|
2378
|
+
apiBaseUrl: "https://api.deepdots.com"
|
|
2251
2379
|
}
|
|
2252
2380
|
};
|
|
2253
2381
|
function resolveEnvironment(nodeEnv) {
|
|
@@ -2329,10 +2457,10 @@ var BrowserPopupRenderer = class {
|
|
|
2329
2457
|
document.body.appendChild(this.container);
|
|
2330
2458
|
}
|
|
2331
2459
|
}
|
|
2332
|
-
show(surveyId, productId, actions, emit, onClose) {
|
|
2460
|
+
show(surveyId, productId, actions, emit, onClose, env = "production") {
|
|
2333
2461
|
if (!this.container) this.init();
|
|
2334
2462
|
if (!this.container) return;
|
|
2335
|
-
renderPopup(this.container, surveyId, productId, actions, emit, onClose);
|
|
2463
|
+
renderPopup(this.container, surveyId, productId, actions, emit, onClose, env);
|
|
2336
2464
|
}
|
|
2337
2465
|
hide() {
|
|
2338
2466
|
if (this.container) {
|
|
@@ -2351,6 +2479,8 @@ function createDefaultRenderer() {
|
|
|
2351
2479
|
}
|
|
2352
2480
|
|
|
2353
2481
|
// src/core/deepdots-popups.ts
|
|
2482
|
+
var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
|
|
2483
|
+
var DAY_IN_MS = 24 * 60 * 60 * 1e3;
|
|
2354
2484
|
var DeepdotsPopups = class {
|
|
2355
2485
|
constructor() {
|
|
2356
2486
|
this.config = null;
|
|
@@ -2364,9 +2494,15 @@ var DeepdotsPopups = class {
|
|
|
2364
2494
|
this.popupsLoaded = false;
|
|
2365
2495
|
this.pendingAutoLaunch = false;
|
|
2366
2496
|
this.answeredSurveys = /* @__PURE__ */ new Set();
|
|
2497
|
+
this.surveyProgress = /* @__PURE__ */ new Map();
|
|
2367
2498
|
this.lastShown = /* @__PURE__ */ new Map();
|
|
2499
|
+
// popupId -> timestamp mostrado
|
|
2500
|
+
this.surveyToPopupId = /* @__PURE__ */ new Map();
|
|
2501
|
+
// surveyId -> popupId
|
|
2502
|
+
this.deferredExitTimers = [];
|
|
2503
|
+
this.baseUrl = "";
|
|
2504
|
+
this.env = "production";
|
|
2368
2505
|
}
|
|
2369
|
-
// popupId -> timestamp mostrado
|
|
2370
2506
|
/** Initialize the SDK with configuration */
|
|
2371
2507
|
init(config) {
|
|
2372
2508
|
if (this.initialized) {
|
|
@@ -2374,27 +2510,31 @@ var DeepdotsPopups = class {
|
|
|
2374
2510
|
return;
|
|
2375
2511
|
}
|
|
2376
2512
|
const env = resolveEnvironment(config.nodeEnv);
|
|
2513
|
+
this.baseUrl = env.apiBaseUrl;
|
|
2514
|
+
this.env = config.nodeEnv || "production";
|
|
2377
2515
|
this.config = {
|
|
2378
2516
|
apiKey: config.apiKey || void 0,
|
|
2379
|
-
baseUrl: env.apiBaseUrl,
|
|
2380
2517
|
mode: config.mode || "client",
|
|
2381
2518
|
debug: config.debug || false,
|
|
2382
|
-
popups: config.popups || []
|
|
2519
|
+
popups: config.popups || [],
|
|
2520
|
+
userId: config.userId || void 0
|
|
2383
2521
|
};
|
|
2384
2522
|
this.initialized = true;
|
|
2385
2523
|
this.log("SDK initialized", this.config);
|
|
2386
2524
|
if (this.renderer.init) this.renderer.init();
|
|
2387
2525
|
this.setupPopupContainer();
|
|
2388
2526
|
if (this.config.mode === "client") {
|
|
2389
|
-
this.popupDefinitions = this.config.popups || [];
|
|
2527
|
+
this.popupDefinitions = this.validatePopupDefinitions(this.config.popups || []);
|
|
2390
2528
|
this.popupsLoaded = true;
|
|
2391
2529
|
this.configureTriggersFromDefinitions();
|
|
2530
|
+
this.processDeferredExitQueue();
|
|
2392
2531
|
} else {
|
|
2393
2532
|
this.fetchPopupsFromServer().then((defs) => {
|
|
2394
|
-
this.popupDefinitions = defs;
|
|
2533
|
+
this.popupDefinitions = this.validatePopupDefinitions(defs);
|
|
2395
2534
|
this.popupsLoaded = true;
|
|
2396
|
-
this.log("Popups loaded from server (fake)",
|
|
2535
|
+
this.log("Popups loaded from server (fake)", this.popupDefinitions);
|
|
2397
2536
|
this.configureTriggersFromDefinitions();
|
|
2537
|
+
this.processDeferredExitQueue();
|
|
2398
2538
|
if (this.pendingAutoLaunch) {
|
|
2399
2539
|
this.startTriggers();
|
|
2400
2540
|
}
|
|
@@ -2420,7 +2560,6 @@ var DeepdotsPopups = class {
|
|
|
2420
2560
|
}
|
|
2421
2561
|
/** Show a popup immediately (supports legacy ShowOptions and new PopupDefinition) */
|
|
2422
2562
|
show(options) {
|
|
2423
|
-
console.log("Show popup called with options:", options);
|
|
2424
2563
|
if (!this.initialized) {
|
|
2425
2564
|
throw new Error("SDK not initialized. Call init() first.");
|
|
2426
2565
|
}
|
|
@@ -2428,8 +2567,10 @@ var DeepdotsPopups = class {
|
|
|
2428
2567
|
if (isDefinition) {
|
|
2429
2568
|
const def = options;
|
|
2430
2569
|
this.log("Showing popup (definition)", def);
|
|
2570
|
+
this.surveyToPopupId.set(def.surveyId, def.id);
|
|
2571
|
+
this.lastShown.set(def.id, Date.now());
|
|
2431
2572
|
this.renderPopup(def.surveyId, def.productId, def.actions);
|
|
2432
|
-
this.emitEvent("popup_shown", def.surveyId);
|
|
2573
|
+
this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
|
|
2433
2574
|
} else {
|
|
2434
2575
|
const opt = options;
|
|
2435
2576
|
this.log("Showing popup (legacy options)", opt);
|
|
@@ -2439,7 +2580,7 @@ var DeepdotsPopups = class {
|
|
|
2439
2580
|
}
|
|
2440
2581
|
/** Mostrar popup por id de definición (usa surveyId interno) */
|
|
2441
2582
|
showByPopupId(popupId) {
|
|
2442
|
-
const def = this.popupDefinitions.find((
|
|
2583
|
+
const def = this.popupDefinitions.find((popup) => popup.id === popupId);
|
|
2443
2584
|
if (!def) {
|
|
2444
2585
|
this.log("Popup definition not found", popupId);
|
|
2445
2586
|
return;
|
|
@@ -2457,92 +2598,315 @@ var DeepdotsPopups = class {
|
|
|
2457
2598
|
/** Deriva triggers desde las definiciones de popup */
|
|
2458
2599
|
configureTriggersFromDefinitions() {
|
|
2459
2600
|
const derived = [];
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
case "time_on_page":
|
|
2467
|
-
type = "time";
|
|
2468
|
-
break;
|
|
2469
|
-
case "scroll":
|
|
2470
|
-
type = "scroll";
|
|
2471
|
-
break;
|
|
2472
|
-
case "exit":
|
|
2473
|
-
type = "exit";
|
|
2474
|
-
break;
|
|
2475
|
-
default:
|
|
2476
|
-
this.debug("Unsupported trigger type", t.type);
|
|
2601
|
+
this.debug("Validated popup definitions", this.popupDefinitions);
|
|
2602
|
+
this.popupDefinitions.forEach((def) => {
|
|
2603
|
+
def.triggers.forEach((trigger) => {
|
|
2604
|
+
const type = this.mapPopupTriggerType(trigger.type);
|
|
2605
|
+
if (!type) {
|
|
2606
|
+
this.debug("Unsupported trigger type", trigger.type);
|
|
2477
2607
|
return;
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2608
|
+
}
|
|
2609
|
+
const value = type === "time" && typeof trigger.value === "number" ? trigger.value * 1e3 : trigger.value;
|
|
2610
|
+
derived.push({ type, value, surveyId: def.surveyId, popupId: def.id });
|
|
2611
|
+
});
|
|
2481
2612
|
});
|
|
2482
2613
|
if (derived.length) {
|
|
2483
2614
|
this.configureTriggers(derived);
|
|
2484
2615
|
}
|
|
2485
2616
|
}
|
|
2486
2617
|
/** Lógica para evaluar condiciones antes de mostrar una encuesta */
|
|
2487
|
-
triggerSurvey(surveyId) {
|
|
2488
|
-
const def = this.
|
|
2618
|
+
triggerSurvey(surveyId, popupId) {
|
|
2619
|
+
const def = this.findPopupDefinition(surveyId, popupId);
|
|
2489
2620
|
if (!def) {
|
|
2490
|
-
this.debug("No popup definition for
|
|
2621
|
+
this.debug("No popup definition for trigger", { surveyId, popupId });
|
|
2491
2622
|
return;
|
|
2492
2623
|
}
|
|
2493
2624
|
if (!this.shouldShow(def)) {
|
|
2494
2625
|
this.debug("Conditions prevented showing popup", def.id);
|
|
2495
2626
|
return;
|
|
2496
2627
|
}
|
|
2628
|
+
this.showDefinition(def);
|
|
2629
|
+
}
|
|
2630
|
+
/** Trigger popups configured with trigger.type = 'event' and matching trigger.value */
|
|
2631
|
+
triggerEvent(eventName) {
|
|
2632
|
+
if (!this.initialized) {
|
|
2633
|
+
throw new Error("SDK not initialized. Call init() first.");
|
|
2634
|
+
}
|
|
2635
|
+
const normalized = String(eventName || "").trim();
|
|
2636
|
+
if (!normalized) {
|
|
2637
|
+
this.debug("Ignoring empty event trigger name");
|
|
2638
|
+
return;
|
|
2639
|
+
}
|
|
2640
|
+
const candidates = this.popupDefinitions.filter((def) => {
|
|
2641
|
+
return def.triggers.some((trigger) => {
|
|
2642
|
+
const triggerValue = String(trigger.value ?? "").trim();
|
|
2643
|
+
return trigger.type === "event" && triggerValue === normalized;
|
|
2644
|
+
});
|
|
2645
|
+
});
|
|
2646
|
+
if (!candidates.length) {
|
|
2647
|
+
this.debug("No event popup definitions found", { eventName: normalized });
|
|
2648
|
+
return;
|
|
2649
|
+
}
|
|
2650
|
+
const matched = candidates.find((def) => this.shouldShow(def));
|
|
2651
|
+
if (!matched) {
|
|
2652
|
+
this.debug("Event popup blocked by conditions/segments", { eventName: normalized });
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
this.showDefinition(matched);
|
|
2656
|
+
}
|
|
2657
|
+
showDefinition(def) {
|
|
2497
2658
|
this.show(def);
|
|
2498
|
-
this.lastShown.set(def.id, Date.now());
|
|
2499
2659
|
}
|
|
2500
|
-
shouldShow(def) {
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2660
|
+
shouldShow(def, pathUrl, skipPathCheck = false) {
|
|
2661
|
+
if (!skipPathCheck && !this.matchesSegmentsPath(def, pathUrl)) {
|
|
2662
|
+
return false;
|
|
2663
|
+
}
|
|
2664
|
+
const cooldowns = def.cooldown || [];
|
|
2665
|
+
if (cooldowns.length && !cooldowns.every((cooldown) => this.evaluateCooldown(def, cooldown))) {
|
|
2666
|
+
return false;
|
|
2667
|
+
}
|
|
2668
|
+
const legacyConditions = def.legacyConditions || [];
|
|
2669
|
+
if (!legacyConditions.length) return true;
|
|
2670
|
+
return legacyConditions.every((condition) => this.evaluateLegacyCondition(def, condition));
|
|
2504
2671
|
}
|
|
2505
|
-
|
|
2672
|
+
matchesSegmentsPath(def, pathUrl) {
|
|
2673
|
+
const paths = def.segments?.path;
|
|
2674
|
+
if (!paths || paths.length === 0) return true;
|
|
2675
|
+
if (typeof window === "undefined" || !window.location) {
|
|
2676
|
+
this.debug("No window.location available for path comparison", { popupId: def.id, paths });
|
|
2677
|
+
return true;
|
|
2678
|
+
}
|
|
2679
|
+
const normalizedHref = this.normalizeUrl(pathUrl || window.location.href || "");
|
|
2680
|
+
const currentUrl = this.safeParseUrl(normalizedHref);
|
|
2681
|
+
const normalizedPath = this.normalizeUrl(currentUrl?.pathname || window.location.pathname || "");
|
|
2682
|
+
const matches = paths.some((rawCandidate) => {
|
|
2683
|
+
const candidate = this.normalizeUrl(rawCandidate);
|
|
2684
|
+
let match = false;
|
|
2685
|
+
if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
|
|
2686
|
+
match = normalizedHref === candidate;
|
|
2687
|
+
} else if (candidate.startsWith("/")) {
|
|
2688
|
+
match = normalizedHref.includes(candidate);
|
|
2689
|
+
} else {
|
|
2690
|
+
match = normalizedPath === candidate;
|
|
2691
|
+
}
|
|
2692
|
+
this.debug("Path comparison", {
|
|
2693
|
+
popupId: def.id,
|
|
2694
|
+
candidate,
|
|
2695
|
+
currentPath: normalizedPath,
|
|
2696
|
+
currentHref: normalizedHref,
|
|
2697
|
+
match
|
|
2698
|
+
});
|
|
2699
|
+
return match;
|
|
2700
|
+
});
|
|
2701
|
+
if (!matches) {
|
|
2702
|
+
this.debug("No path match for popup", { popupId: def.id, paths, currentPath: normalizedPath });
|
|
2703
|
+
}
|
|
2704
|
+
return matches;
|
|
2705
|
+
}
|
|
2706
|
+
evaluateCooldown(def, condition) {
|
|
2707
|
+
switch (condition.answered) {
|
|
2708
|
+
case "SHOWED":
|
|
2709
|
+
return this.hasCooldownElapsed(this.lastShown.get(def.id), condition.cooldownDays);
|
|
2710
|
+
case "PARTIAL":
|
|
2711
|
+
case "COMPLETED": {
|
|
2712
|
+
const progress = this.surveyProgress.get(def.surveyId);
|
|
2713
|
+
if (!progress || progress.status !== condition.answered) {
|
|
2714
|
+
return true;
|
|
2715
|
+
}
|
|
2716
|
+
return this.hasCooldownElapsed(progress.timestamp, condition.cooldownDays);
|
|
2717
|
+
}
|
|
2718
|
+
default:
|
|
2719
|
+
return true;
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
evaluateLegacyCondition(def, condition) {
|
|
2506
2723
|
if (!condition.answered && this.answeredSurveys.has(def.surveyId)) {
|
|
2507
2724
|
return false;
|
|
2508
2725
|
}
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
if (msSince < required) return false;
|
|
2515
|
-
}
|
|
2726
|
+
return this.hasCooldownElapsed(this.lastShown.get(def.id), condition.cooldownDays);
|
|
2727
|
+
}
|
|
2728
|
+
hasCooldownElapsed(timestamp, cooldownDays) {
|
|
2729
|
+
if (!timestamp || !cooldownDays) {
|
|
2730
|
+
return true;
|
|
2516
2731
|
}
|
|
2517
|
-
return
|
|
2732
|
+
return Date.now() - timestamp >= cooldownDays * DAY_IN_MS;
|
|
2518
2733
|
}
|
|
2519
2734
|
/** Marcar encuesta como contestada externamente */
|
|
2520
2735
|
markSurveyAnswered(surveyId) {
|
|
2521
2736
|
this.answeredSurveys.add(surveyId);
|
|
2737
|
+
this.markSurveyProgress(surveyId, "COMPLETED");
|
|
2738
|
+
}
|
|
2739
|
+
/** Queue an exit popup so it can render after navigation */
|
|
2740
|
+
queueExitPopup(surveyId, delaySeconds, sourceUrl, popupId) {
|
|
2741
|
+
const def = this.findPopupDefinition(surveyId, popupId);
|
|
2742
|
+
if (!def) {
|
|
2743
|
+
this.debug("No popup definition for exit trigger", { surveyId, popupId });
|
|
2744
|
+
return;
|
|
2745
|
+
}
|
|
2746
|
+
const originUrl = sourceUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
2747
|
+
if (!originUrl) {
|
|
2748
|
+
this.debug("Exit popup skipped: missing source URL", { surveyId });
|
|
2749
|
+
return;
|
|
2750
|
+
}
|
|
2751
|
+
if (!this.shouldShow(def, originUrl)) {
|
|
2752
|
+
this.debug("Exit popup skipped by conditions/path", { popupId: def.id, sourceUrl: originUrl });
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
const safeDelayMs = Number.isFinite(delaySeconds) ? Math.max(0, delaySeconds * 1e3) : 0;
|
|
2756
|
+
const deferred = {
|
|
2757
|
+
id: def.id,
|
|
2758
|
+
surveyId: def.surveyId,
|
|
2759
|
+
sourceUrl: this.normalizeUrl(originUrl),
|
|
2760
|
+
dueAt: Date.now() + safeDelayMs
|
|
2761
|
+
};
|
|
2762
|
+
const queue = this.getDeferredExitQueue().filter((item) => !(item.id === deferred.id && item.sourceUrl === deferred.sourceUrl));
|
|
2763
|
+
queue.push(deferred);
|
|
2764
|
+
this.setDeferredExitQueue(queue);
|
|
2765
|
+
this.scheduleDeferredExitPopup(deferred);
|
|
2766
|
+
this.debug("Exit popup queued", deferred);
|
|
2767
|
+
}
|
|
2768
|
+
processDeferredExitQueue() {
|
|
2769
|
+
const queue = this.getDeferredExitQueue();
|
|
2770
|
+
if (!queue.length) return;
|
|
2771
|
+
const pending = [];
|
|
2772
|
+
const now = Date.now();
|
|
2773
|
+
queue.forEach((item) => {
|
|
2774
|
+
const def = this.popupDefinitions.find((popup) => popup.id === item.id && popup.surveyId === item.surveyId);
|
|
2775
|
+
if (!def) {
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
if (item.dueAt <= now) {
|
|
2779
|
+
this.tryShowDeferredExitPopup(item);
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
pending.push(item);
|
|
2783
|
+
this.scheduleDeferredExitPopup(item);
|
|
2784
|
+
});
|
|
2785
|
+
this.setDeferredExitQueue(pending);
|
|
2786
|
+
}
|
|
2787
|
+
scheduleDeferredExitPopup(item) {
|
|
2788
|
+
if (typeof window === "undefined") return;
|
|
2789
|
+
const delay = Math.max(0, item.dueAt - Date.now());
|
|
2790
|
+
const timer = window.setTimeout(() => this.tryShowDeferredExitPopup(item), delay);
|
|
2791
|
+
this.deferredExitTimers.push(timer);
|
|
2792
|
+
}
|
|
2793
|
+
tryShowDeferredExitPopup(item) {
|
|
2794
|
+
const def = this.popupDefinitions.find((popup) => popup.id === item.id && popup.surveyId === item.surveyId);
|
|
2795
|
+
if (!def) {
|
|
2796
|
+
this.removeDeferredExitPopup(item);
|
|
2797
|
+
return;
|
|
2798
|
+
}
|
|
2799
|
+
const currentUrl = typeof window !== "undefined" ? this.normalizeUrl(window.location.href || "") : "";
|
|
2800
|
+
if (!currentUrl || currentUrl === this.normalizeUrl(item.sourceUrl)) {
|
|
2801
|
+
this.removeDeferredExitPopup(item);
|
|
2802
|
+
this.debug("Exit popup dropped because route did not change", item);
|
|
2803
|
+
return;
|
|
2804
|
+
}
|
|
2805
|
+
if (!this.shouldShow(def, void 0, true)) {
|
|
2806
|
+
this.removeDeferredExitPopup(item);
|
|
2807
|
+
this.debug("Exit popup skipped at render-time conditions", item);
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
this.showDefinition(def);
|
|
2811
|
+
this.removeDeferredExitPopup(item);
|
|
2522
2812
|
}
|
|
2523
|
-
|
|
2813
|
+
findPopupDefinition(surveyId, popupId) {
|
|
2814
|
+
if (popupId) {
|
|
2815
|
+
const byId = this.popupDefinitions.find((popup) => popup.id === popupId);
|
|
2816
|
+
if (byId) return byId;
|
|
2817
|
+
}
|
|
2818
|
+
return this.popupDefinitions.find((popup) => popup.surveyId === surveyId);
|
|
2819
|
+
}
|
|
2820
|
+
removeDeferredExitPopup(item) {
|
|
2821
|
+
const queue = this.getDeferredExitQueue().filter((entry) => !(entry.id === item.id && entry.sourceUrl === item.sourceUrl));
|
|
2822
|
+
this.setDeferredExitQueue(queue);
|
|
2823
|
+
}
|
|
2824
|
+
getDeferredExitQueue() {
|
|
2825
|
+
if (typeof window === "undefined") return [];
|
|
2826
|
+
try {
|
|
2827
|
+
const raw = window.sessionStorage.getItem(EXIT_QUEUE_STORAGE_KEY);
|
|
2828
|
+
if (!raw) return [];
|
|
2829
|
+
const parsed = JSON.parse(raw);
|
|
2830
|
+
if (!Array.isArray(parsed)) return [];
|
|
2831
|
+
return parsed.filter((entry) => {
|
|
2832
|
+
if (typeof entry !== "object" || entry === null) return false;
|
|
2833
|
+
const item = entry;
|
|
2834
|
+
return typeof item.id === "string" && typeof item.surveyId === "string" && typeof item.sourceUrl === "string" && typeof item.dueAt === "number" && Number.isFinite(item.dueAt);
|
|
2835
|
+
}).map((item) => ({
|
|
2836
|
+
...item,
|
|
2837
|
+
sourceUrl: this.normalizeUrl(item.sourceUrl)
|
|
2838
|
+
}));
|
|
2839
|
+
} catch {
|
|
2840
|
+
return [];
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
setDeferredExitQueue(queue) {
|
|
2844
|
+
if (typeof window === "undefined") return;
|
|
2845
|
+
try {
|
|
2846
|
+
if (!queue.length) {
|
|
2847
|
+
window.sessionStorage.removeItem(EXIT_QUEUE_STORAGE_KEY);
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
window.sessionStorage.setItem(EXIT_QUEUE_STORAGE_KEY, JSON.stringify(queue));
|
|
2851
|
+
} catch {
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
/** Fetch al servidor para obtener popups */
|
|
2524
2855
|
async fetchPopupsFromServer() {
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
surveyId: "survey-abc",
|
|
2541
|
-
productId: "product-xyz",
|
|
2542
|
-
style: { theme: "light", position: "bottom-right", imageUrl: null },
|
|
2543
|
-
segments: { lang: ["en"], path: ["/checkout"] }
|
|
2856
|
+
const apiKey = this.config?.apiKey;
|
|
2857
|
+
const baseUrl = this.baseUrl;
|
|
2858
|
+
const userId = this.config?.userId;
|
|
2859
|
+
if (!apiKey || !baseUrl) {
|
|
2860
|
+
this.log("Missing apiKey or baseUrl. Skipping popups fetch.");
|
|
2861
|
+
return [];
|
|
2862
|
+
}
|
|
2863
|
+
const filter = userId ? { where: { userId } } : null;
|
|
2864
|
+
const query = filter ? `?filter=${encodeURIComponent(JSON.stringify(filter))}` : "";
|
|
2865
|
+
const endpoint = `${baseUrl}/sdk/${encodeURIComponent(apiKey)}/popups${query}`;
|
|
2866
|
+
try {
|
|
2867
|
+
const response = await fetch(endpoint);
|
|
2868
|
+
if (!response.ok) {
|
|
2869
|
+
this.log("Failed to fetch popups", response.status, response.statusText);
|
|
2870
|
+
return [];
|
|
2544
2871
|
}
|
|
2545
|
-
|
|
2872
|
+
const raw = await response.text();
|
|
2873
|
+
const parsed = JSON.parse(raw);
|
|
2874
|
+
if (!Array.isArray(parsed)) {
|
|
2875
|
+
this.log("Unexpected popups payload", parsed);
|
|
2876
|
+
return [];
|
|
2877
|
+
}
|
|
2878
|
+
this.debug("Fetched popups payload", parsed);
|
|
2879
|
+
return parsed;
|
|
2880
|
+
} catch (error) {
|
|
2881
|
+
this.log("Error fetching popups", error);
|
|
2882
|
+
return [];
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
/** Notifica eventos de popup a la API */
|
|
2886
|
+
async postPopupEvent(status, popupId, userId) {
|
|
2887
|
+
const apiKey = this.config?.apiKey;
|
|
2888
|
+
const baseUrl = this.baseUrl;
|
|
2889
|
+
if (!apiKey || !baseUrl) {
|
|
2890
|
+
return;
|
|
2891
|
+
}
|
|
2892
|
+
const endpoint = `${baseUrl}/sdk/popups`;
|
|
2893
|
+
try {
|
|
2894
|
+
const response = await fetch(endpoint, {
|
|
2895
|
+
method: "POST",
|
|
2896
|
+
headers: { "Content-Type": "application/json" },
|
|
2897
|
+
body: JSON.stringify({
|
|
2898
|
+
publicKey: apiKey,
|
|
2899
|
+
status,
|
|
2900
|
+
popupId,
|
|
2901
|
+
userId: userId || void 0
|
|
2902
|
+
})
|
|
2903
|
+
});
|
|
2904
|
+
if (!response.ok) {
|
|
2905
|
+
this.log("Failed to post popup event", response.status, response.statusText);
|
|
2906
|
+
}
|
|
2907
|
+
} catch (error) {
|
|
2908
|
+
this.log("Error posting popup event", error);
|
|
2909
|
+
}
|
|
2546
2910
|
}
|
|
2547
2911
|
/** Add an event listener */
|
|
2548
2912
|
on(eventType, listener) {
|
|
@@ -2582,11 +2946,26 @@ var DeepdotsPopups = class {
|
|
|
2582
2946
|
/** Render the popup UI */
|
|
2583
2947
|
renderPopup(surveyId, productId, actions) {
|
|
2584
2948
|
if (this.renderer) {
|
|
2585
|
-
this.renderer.show(
|
|
2949
|
+
this.renderer.show(
|
|
2950
|
+
surveyId,
|
|
2951
|
+
productId,
|
|
2952
|
+
actions,
|
|
2953
|
+
(type, id, payload) => this.emitEvent(type, id, payload),
|
|
2954
|
+
() => this.hidePopup(),
|
|
2955
|
+
this.env
|
|
2956
|
+
);
|
|
2586
2957
|
return;
|
|
2587
2958
|
}
|
|
2588
2959
|
if (!this.popupContainer) return;
|
|
2589
|
-
renderPopup(
|
|
2960
|
+
renderPopup(
|
|
2961
|
+
this.popupContainer,
|
|
2962
|
+
surveyId,
|
|
2963
|
+
productId,
|
|
2964
|
+
actions,
|
|
2965
|
+
(type, id, payload) => this.emitEvent(type, id, payload),
|
|
2966
|
+
() => this.hidePopup(),
|
|
2967
|
+
this.env
|
|
2968
|
+
);
|
|
2590
2969
|
}
|
|
2591
2970
|
/** Hide the popup */
|
|
2592
2971
|
hidePopup() {
|
|
@@ -2603,9 +2982,22 @@ var DeepdotsPopups = class {
|
|
|
2603
2982
|
emitEvent(type, surveyId, data) {
|
|
2604
2983
|
const event = { type, surveyId, timestamp: Date.now(), data };
|
|
2605
2984
|
this.log("Event emitted", event);
|
|
2985
|
+
if (type === "popup_clicked" && data?.action === "partial") {
|
|
2986
|
+
this.markSurveyProgress(surveyId, "PARTIAL");
|
|
2987
|
+
}
|
|
2606
2988
|
if (type === "survey_completed") {
|
|
2607
2989
|
this.markSurveyAnswered(surveyId);
|
|
2608
2990
|
}
|
|
2991
|
+
if (type === "popup_shown" || type === "survey_completed") {
|
|
2992
|
+
const popupIdFromData = data?.popupId;
|
|
2993
|
+
const popupId = popupIdFromData || this.surveyToPopupId.get(surveyId);
|
|
2994
|
+
if (popupId) {
|
|
2995
|
+
const userIdFromData = data?.userId;
|
|
2996
|
+
void this.postPopupEvent(type === "popup_shown" ? "opened" : "completed", popupId, userIdFromData || this.config?.userId);
|
|
2997
|
+
} else {
|
|
2998
|
+
this.debug("No popupId available to post event", { type, surveyId });
|
|
2999
|
+
}
|
|
3000
|
+
}
|
|
2609
3001
|
const listeners = this.listeners.get(type);
|
|
2610
3002
|
if (listeners) {
|
|
2611
3003
|
listeners.forEach((listener) => {
|
|
@@ -2634,17 +3026,111 @@ var DeepdotsPopups = class {
|
|
|
2634
3026
|
this.renderer.init();
|
|
2635
3027
|
}
|
|
2636
3028
|
}
|
|
2637
|
-
|
|
3029
|
+
normalizeUrl(value) {
|
|
3030
|
+
if (!value) return "";
|
|
3031
|
+
const withoutIndex = value.replace(/\/index\.html(?=($|[?#]))/i, "");
|
|
3032
|
+
return withoutIndex.length > 1 && withoutIndex.endsWith("/") ? withoutIndex.slice(0, -1) : withoutIndex;
|
|
3033
|
+
}
|
|
3034
|
+
safeParseUrl(url) {
|
|
3035
|
+
if (!url) return null;
|
|
3036
|
+
try {
|
|
3037
|
+
return new URL(url, typeof window !== "undefined" ? window.location.href : void 0);
|
|
3038
|
+
} catch {
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
}
|
|
3042
|
+
mapPopupTriggerType(type) {
|
|
3043
|
+
switch (type) {
|
|
3044
|
+
case "time_on_page":
|
|
3045
|
+
return "time";
|
|
3046
|
+
case "scroll":
|
|
3047
|
+
return "scroll";
|
|
3048
|
+
case "exit":
|
|
3049
|
+
return "exit";
|
|
3050
|
+
case "click":
|
|
3051
|
+
return "click";
|
|
3052
|
+
case "event":
|
|
3053
|
+
return "event";
|
|
3054
|
+
default:
|
|
3055
|
+
return null;
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
markSurveyProgress(surveyId, status) {
|
|
3059
|
+
const current = this.surveyProgress.get(surveyId);
|
|
3060
|
+
if (current?.status === "COMPLETED" && status !== "COMPLETED") {
|
|
3061
|
+
return;
|
|
3062
|
+
}
|
|
3063
|
+
this.surveyProgress.set(surveyId, { status, timestamp: Date.now() });
|
|
3064
|
+
}
|
|
2638
3065
|
isPopupDefinition(value) {
|
|
2639
3066
|
if (typeof value !== "object" || value === null) return false;
|
|
2640
|
-
const
|
|
2641
|
-
return typeof
|
|
3067
|
+
const popup = value;
|
|
3068
|
+
return typeof popup.id === "string" && typeof popup.title === "string" && typeof popup.message === "string" && typeof popup.surveyId === "string" && typeof popup.productId === "string" && Array.isArray(popup.triggers) && popup.triggers.length > 0 && popup.triggers.every((trigger) => this.isPopupTrigger(trigger)) && (!popup.cooldown || popup.cooldown.every((condition) => this.isPopupTriggerCondition(condition)));
|
|
3069
|
+
}
|
|
3070
|
+
isPopupTrigger(value) {
|
|
3071
|
+
if (typeof value !== "object" || value === null) return false;
|
|
3072
|
+
const trigger = value;
|
|
3073
|
+
return this.isPopupTriggerType(trigger.type) && (typeof trigger.value === "number" || typeof trigger.value === "string");
|
|
3074
|
+
}
|
|
3075
|
+
isPopupTriggerType(value) {
|
|
3076
|
+
return value === "time_on_page" || value === "scroll" || value === "exit" || value === "click" || value === "event";
|
|
3077
|
+
}
|
|
3078
|
+
isPopupTriggerCondition(value) {
|
|
3079
|
+
if (typeof value !== "object" || value === null) return false;
|
|
3080
|
+
const condition = value;
|
|
3081
|
+
return POPUP_TRIGGER_CONDITION_STATUSES.includes(condition.answered) && typeof condition.cooldownDays === "number" && Number.isFinite(condition.cooldownDays) && condition.cooldownDays >= 0;
|
|
3082
|
+
}
|
|
3083
|
+
isLegacyPopupTriggerCondition(value) {
|
|
3084
|
+
if (typeof value !== "object" || value === null) return false;
|
|
3085
|
+
const condition = value;
|
|
3086
|
+
if (condition.answered !== void 0 && typeof condition.answered !== "boolean") {
|
|
3087
|
+
return false;
|
|
3088
|
+
}
|
|
3089
|
+
if (condition.cooldownDays !== void 0) {
|
|
3090
|
+
return typeof condition.cooldownDays === "number" && Number.isFinite(condition.cooldownDays) && condition.cooldownDays >= 0;
|
|
3091
|
+
}
|
|
3092
|
+
return true;
|
|
3093
|
+
}
|
|
3094
|
+
normalizeTriggers(value) {
|
|
3095
|
+
const items = Array.isArray(value) ? value : value ? [value] : [];
|
|
3096
|
+
return items.filter((trigger) => this.isPopupTrigger(trigger)).map((trigger) => ({
|
|
3097
|
+
type: trigger.type,
|
|
3098
|
+
value: trigger.value
|
|
3099
|
+
}));
|
|
3100
|
+
}
|
|
3101
|
+
normalizeCooldown(value) {
|
|
3102
|
+
if (!Array.isArray(value)) return [];
|
|
3103
|
+
return value.filter((condition) => this.isPopupTriggerCondition(condition));
|
|
3104
|
+
}
|
|
3105
|
+
normalizeLegacyConditions(value) {
|
|
3106
|
+
if (!Array.isArray(value)) return [];
|
|
3107
|
+
return value.filter((condition) => this.isLegacyPopupTriggerCondition(condition));
|
|
3108
|
+
}
|
|
3109
|
+
normalizePopupDefinition(def) {
|
|
3110
|
+
if (typeof def !== "object" || def === null) return null;
|
|
3111
|
+
const raw = def;
|
|
3112
|
+
const rawTriggers = raw.triggers ?? raw.trigger;
|
|
3113
|
+
const triggers = this.normalizeTriggers(rawTriggers);
|
|
3114
|
+
if (!triggers.length) return null;
|
|
3115
|
+
const rawTriggerList = Array.isArray(rawTriggers) ? rawTriggers : rawTriggers ? [rawTriggers] : [];
|
|
3116
|
+
const legacyConditions = [
|
|
3117
|
+
...this.normalizeLegacyConditions(raw.conditions),
|
|
3118
|
+
...rawTriggerList.flatMap((trigger) => this.normalizeLegacyConditions(trigger.condition))
|
|
3119
|
+
];
|
|
3120
|
+
const cooldown = this.normalizeCooldown(raw.cooldown);
|
|
3121
|
+
return {
|
|
3122
|
+
...raw,
|
|
3123
|
+
triggers,
|
|
3124
|
+
cooldown,
|
|
3125
|
+
legacyConditions
|
|
3126
|
+
};
|
|
2642
3127
|
}
|
|
2643
3128
|
validatePopupDefinitions(defs) {
|
|
2644
|
-
return defs.filter((
|
|
3129
|
+
return defs.map((def) => this.normalizePopupDefinition(def)).filter((def) => !!def && this.isPopupDefinition(def));
|
|
2645
3130
|
}
|
|
2646
3131
|
};
|
|
2647
3132
|
export {
|
|
2648
|
-
DeepdotsPopups
|
|
3133
|
+
DeepdotsPopups,
|
|
3134
|
+
POPUP_TRIGGER_CONDITION_STATUSES
|
|
2649
3135
|
};
|
|
2650
3136
|
//# sourceMappingURL=index.mjs.map
|