@magicfeedback/popup-sdk 1.7.2 → 1.8.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.
@@ -2373,6 +2373,9 @@ var DeepdotsPopups = class {
2373
2373
  this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
2374
2374
  }
2375
2375
  shouldShow(def, pathUrl, skipPathCheck = false) {
2376
+ if (this.isPathExcluded(def, pathUrl)) {
2377
+ return false;
2378
+ }
2376
2379
  if (!skipPathCheck && !this.matchesSegmentsPath(def, pathUrl)) {
2377
2380
  return false;
2378
2381
  }
@@ -2403,40 +2406,85 @@ var DeepdotsPopups = class {
2403
2406
  }
2404
2407
  return matches;
2405
2408
  }
2409
+ /** `segments.path`: rutas donde el popup PUEDE mostrarse. Sin lista, en todas. */
2406
2410
  matchesSegmentsPath(def, pathUrl) {
2407
2411
  const paths = def.segments?.path;
2408
- if (!paths || paths.length === 0) return true;
2409
- if (typeof window === "undefined" || !window.location) {
2412
+ if (!Array.isArray(paths) || paths.length === 0) return true;
2413
+ const location = this.resolveCurrentLocation(pathUrl);
2414
+ if (!location) {
2410
2415
  this.debug("No window.location available for path comparison", { popupId: def.id, paths });
2411
2416
  return true;
2412
2417
  }
2413
- const normalizedHref = this.normalizeUrl(pathUrl || window.location.href || "");
2414
- const currentUrl = this.safeParseUrl(normalizedHref);
2415
- const normalizedPath = this.normalizeUrl(currentUrl?.pathname || window.location.pathname || "");
2416
2418
  const matches = paths.some((rawCandidate) => {
2417
- const candidate = this.normalizeUrl(rawCandidate);
2418
- let match = false;
2419
- if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
2420
- match = normalizedHref === candidate;
2421
- } else if (candidate.startsWith("/")) {
2422
- match = normalizedHref.includes(candidate);
2423
- } else {
2424
- match = normalizedPath === candidate;
2425
- }
2419
+ const match = this.matchesPathCandidate(rawCandidate, location);
2426
2420
  this.debug("Path comparison", {
2427
2421
  popupId: def.id,
2428
- candidate,
2429
- currentPath: normalizedPath,
2430
- currentHref: normalizedHref,
2422
+ candidate: rawCandidate,
2423
+ currentPath: location.path,
2424
+ currentHref: location.href,
2431
2425
  match
2432
2426
  });
2433
2427
  return match;
2434
2428
  });
2435
2429
  if (!matches) {
2436
- this.debug("No path match for popup", { popupId: def.id, paths, currentPath: normalizedPath });
2430
+ this.debug("No path match for popup", { popupId: def.id, paths, currentPath: location.path });
2437
2431
  }
2438
2432
  return matches;
2439
2433
  }
2434
+ /**
2435
+ * `segments.excludedPaths`: rutas donde el popup NO debe mostrarse. Gana sobre
2436
+ * `segments.path` (`path: ['/']` + `excludedPaths: ['/cart']` = en todas menos el
2437
+ * carrito) y se aplica también cuando no hay `path` (= en todas menos las excluidas).
2438
+ */
2439
+ isPathExcluded(def, pathUrl) {
2440
+ const excluded = def.segments?.excludedPaths;
2441
+ if (!Array.isArray(excluded) || excluded.length === 0) return false;
2442
+ const location = this.resolveCurrentLocation(pathUrl);
2443
+ if (!location) {
2444
+ this.debug("No window.location available for excluded path comparison", { popupId: def.id, excluded });
2445
+ return false;
2446
+ }
2447
+ const hit = excluded.find((rawCandidate) => this.matchesPathCandidate(rawCandidate, location));
2448
+ if (hit !== void 0) {
2449
+ this.debug("Popup excluded by path", {
2450
+ popupId: def.id,
2451
+ candidate: hit,
2452
+ currentPath: location.path,
2453
+ currentHref: location.href
2454
+ });
2455
+ return true;
2456
+ }
2457
+ return false;
2458
+ }
2459
+ /**
2460
+ * Compara UN candidato de `segments.path`/`segments.excludedPaths` con la ruta
2461
+ * actual. Mismas reglas para incluir y para excluir:
2462
+ * - URL absoluta → href completo exacto
2463
+ * - empieza por / → subcadena del href (así entran las rutas con hash: `/#/home`)
2464
+ * - resto → pathname exacto
2465
+ * Ignora entradas que no sean string: el backend puede colar un `null` en la lista
2466
+ * y no puede tumbar la evaluación del trigger entero (mismo fallo que hubo con
2467
+ * `segments.lang`).
2468
+ */
2469
+ matchesPathCandidate(rawCandidate, location) {
2470
+ if (typeof rawCandidate !== "string") return false;
2471
+ const candidate = this.normalizeUrl(rawCandidate);
2472
+ if (!candidate) return false;
2473
+ if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
2474
+ return location.href === candidate;
2475
+ }
2476
+ if (candidate.startsWith("/")) {
2477
+ return location.href.includes(candidate);
2478
+ }
2479
+ return location.path === candidate;
2480
+ }
2481
+ /** href + pathname normalizados de la ruta a evaluar, o null si no hay `window.location`. */
2482
+ resolveCurrentLocation(pathUrl) {
2483
+ if (typeof window === "undefined" || !window.location) return null;
2484
+ const href = this.normalizeUrl(pathUrl || window.location.href || "");
2485
+ const parsed = this.safeParseUrl(href);
2486
+ return { href, path: this.normalizeUrl(parsed?.pathname || window.location.pathname || "") };
2487
+ }
2440
2488
  evaluateCooldown(def, condition) {
2441
2489
  switch (condition.answered) {
2442
2490
  case "SHOWED":