@magicfeedback/popup-sdk 1.7.2 → 1.8.1
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 +8 -5
- package/dist/{chunk-XHR3MHJO.mjs → chunk-AV2TTQXB.mjs} +20 -1
- package/dist/chunk-AV2TTQXB.mjs.map +1 -0
- package/dist/{chunk-322DDMX6.mjs → chunk-EBJZDVC6.mjs} +20 -1
- package/dist/chunk-EBJZDVC6.mjs.map +1 -0
- package/dist/index.d.mts +29 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +101 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -22
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +20 -0
- package/dist/react-native.d.ts +20 -0
- package/dist/react-native.js +99 -18
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +78 -22
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-5QXL6EJW.mjs → renderPopup-3CZ6WTXF.mjs} +6 -4
- package/dist/renderPopup-3CZ6WTXF.mjs.map +1 -0
- package/dist/{renderPopup-SNDPX5RX.mjs → renderPopup-E2OLIXIQ.mjs} +4 -2
- package/dist/renderPopup-E2OLIXIQ.mjs.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-322DDMX6.mjs.map +0 -1
- package/dist/chunk-XHR3MHJO.mjs.map +0 -1
- package/dist/renderPopup-5QXL6EJW.mjs.map +0 -1
- package/dist/renderPopup-SNDPX5RX.mjs.map +0 -1
package/dist/react-native.d.mts
CHANGED
|
@@ -538,7 +538,27 @@ declare class DeepdotsPopups {
|
|
|
538
538
|
private showDefinition;
|
|
539
539
|
private shouldShow;
|
|
540
540
|
private matchesSegmentsLang;
|
|
541
|
+
/** `segments.path`: rutas donde el popup PUEDE mostrarse. Sin lista, en todas. */
|
|
541
542
|
private matchesSegmentsPath;
|
|
543
|
+
/**
|
|
544
|
+
* `segments.excludedPaths`: rutas donde el popup NO debe mostrarse. Gana sobre
|
|
545
|
+
* `segments.path` (`path: ['/']` + `excludedPaths: ['/cart']` = en todas menos el
|
|
546
|
+
* carrito) y se aplica también cuando no hay `path` (= en todas menos las excluidas).
|
|
547
|
+
*/
|
|
548
|
+
private isPathExcluded;
|
|
549
|
+
/**
|
|
550
|
+
* Compara UN candidato de `segments.path`/`segments.excludedPaths` con la ruta
|
|
551
|
+
* actual. Mismas reglas para incluir y para excluir:
|
|
552
|
+
* - URL absoluta → href completo exacto
|
|
553
|
+
* - empieza por / → subcadena del href (así entran las rutas con hash: `/#/home`)
|
|
554
|
+
* - resto → pathname exacto
|
|
555
|
+
* Ignora entradas que no sean string: el backend puede colar un `null` en la lista
|
|
556
|
+
* y no puede tumbar la evaluación del trigger entero (mismo fallo que hubo con
|
|
557
|
+
* `segments.lang`).
|
|
558
|
+
*/
|
|
559
|
+
private matchesPathCandidate;
|
|
560
|
+
/** href + pathname normalizados de la ruta a evaluar, o null si no hay `window.location`. */
|
|
561
|
+
private resolveCurrentLocation;
|
|
542
562
|
private evaluateCooldown;
|
|
543
563
|
private evaluateLegacyCondition;
|
|
544
564
|
private hasCooldownElapsed;
|
package/dist/react-native.d.ts
CHANGED
|
@@ -538,7 +538,27 @@ declare class DeepdotsPopups {
|
|
|
538
538
|
private showDefinition;
|
|
539
539
|
private shouldShow;
|
|
540
540
|
private matchesSegmentsLang;
|
|
541
|
+
/** `segments.path`: rutas donde el popup PUEDE mostrarse. Sin lista, en todas. */
|
|
541
542
|
private matchesSegmentsPath;
|
|
543
|
+
/**
|
|
544
|
+
* `segments.excludedPaths`: rutas donde el popup NO debe mostrarse. Gana sobre
|
|
545
|
+
* `segments.path` (`path: ['/']` + `excludedPaths: ['/cart']` = en todas menos el
|
|
546
|
+
* carrito) y se aplica también cuando no hay `path` (= en todas menos las excluidas).
|
|
547
|
+
*/
|
|
548
|
+
private isPathExcluded;
|
|
549
|
+
/**
|
|
550
|
+
* Compara UN candidato de `segments.path`/`segments.excludedPaths` con la ruta
|
|
551
|
+
* actual. Mismas reglas para incluir y para excluir:
|
|
552
|
+
* - URL absoluta → href completo exacto
|
|
553
|
+
* - empieza por / → subcadena del href (así entran las rutas con hash: `/#/home`)
|
|
554
|
+
* - resto → pathname exacto
|
|
555
|
+
* Ignora entradas que no sean string: el backend puede colar un `null` en la lista
|
|
556
|
+
* y no puede tumbar la evaluación del trigger entero (mismo fallo que hubo con
|
|
557
|
+
* `segments.lang`).
|
|
558
|
+
*/
|
|
559
|
+
private matchesPathCandidate;
|
|
560
|
+
/** href + pathname normalizados de la ruta a evaluar, o null si no hay `window.location`. */
|
|
561
|
+
private resolveCurrentLocation;
|
|
542
562
|
private evaluateCooldown;
|
|
543
563
|
private evaluateLegacyCondition;
|
|
544
564
|
private hasCooldownElapsed;
|
package/dist/react-native.js
CHANGED
|
@@ -522,6 +522,29 @@ function ddApplySurveyPrimaryColor(el, style){
|
|
|
522
522
|
}
|
|
523
523
|
});
|
|
524
524
|
|
|
525
|
+
// src/ui/busy.ts
|
|
526
|
+
function setSurveyBusy(el, busy) {
|
|
527
|
+
if (!el) return;
|
|
528
|
+
el.style.pointerEvents = busy ? "none" : "";
|
|
529
|
+
el.setAttribute("aria-busy", busy ? "true" : "false");
|
|
530
|
+
if ("inert" in el) {
|
|
531
|
+
el.inert = busy;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
var BUSY_JS;
|
|
535
|
+
var init_busy = __esm({
|
|
536
|
+
"src/ui/busy.ts"() {
|
|
537
|
+
"use strict";
|
|
538
|
+
BUSY_JS = `
|
|
539
|
+
function ddSetSurveyBusy(el, busy){
|
|
540
|
+
if(!el){ return; }
|
|
541
|
+
el.style.pointerEvents = busy ? 'none' : '';
|
|
542
|
+
el.setAttribute('aria-busy', busy ? 'true' : 'false');
|
|
543
|
+
if('inert' in el){ el.inert = busy; }
|
|
544
|
+
}`;
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
|
|
525
548
|
// src/assets/style.css
|
|
526
549
|
var style_default;
|
|
527
550
|
var init_style = __esm({
|
|
@@ -2964,6 +2987,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
|
|
|
2964
2987
|
revealTimer = setTimeout(reveal, REVEAL_TIMEOUT_MS);
|
|
2965
2988
|
function setLoading(isLoading) {
|
|
2966
2989
|
spinnerEl.style.display = isLoading ? "flex" : "none";
|
|
2990
|
+
setSurveyBusy(formWrapper, isLoading);
|
|
2967
2991
|
if (!isLoading) {
|
|
2968
2992
|
formHost.style.visibility = "visible";
|
|
2969
2993
|
revealWhenPainted2();
|
|
@@ -3119,6 +3143,7 @@ var init_renderPopup = __esm({
|
|
|
3119
3143
|
init_font();
|
|
3120
3144
|
init_logo();
|
|
3121
3145
|
init_surveyPalette();
|
|
3146
|
+
init_busy();
|
|
3122
3147
|
init_logger();
|
|
3123
3148
|
init_labels();
|
|
3124
3149
|
init_reveal();
|
|
@@ -3338,6 +3363,7 @@ init_font();
|
|
|
3338
3363
|
init_labels();
|
|
3339
3364
|
init_reveal();
|
|
3340
3365
|
init_surveyPalette();
|
|
3366
|
+
init_busy();
|
|
3341
3367
|
init_style();
|
|
3342
3368
|
var REVEAL_JS = `
|
|
3343
3369
|
function ddCreateReveal(popup, onReveal, timeoutMs){
|
|
@@ -3557,6 +3583,7 @@ ${customCss}
|
|
|
3557
3583
|
var footer=document.getElementById('dd-footer');
|
|
3558
3584
|
var spinner=document.getElementById('dd-spinner');
|
|
3559
3585
|
var formHost=document.getElementById('mf');
|
|
3586
|
+
var formWrapper=document.getElementById('dd-form-wrapper');
|
|
3560
3587
|
var errorHint=document.getElementById('dd-error');
|
|
3561
3588
|
var backBtn=document.getElementById('dd-back');
|
|
3562
3589
|
var startBtn=document.getElementById('dd-start');
|
|
@@ -3716,6 +3743,7 @@ ${customCss}
|
|
|
3716
3743
|
}
|
|
3717
3744
|
|
|
3718
3745
|
${PRIMARY_COLOR_JS}
|
|
3746
|
+
${BUSY_JS}
|
|
3719
3747
|
${REVEAL_JS}
|
|
3720
3748
|
// El popup se ense\xF1a cuando el survey est\xE1 pintado; \`ready\` deja al host abrir su propio
|
|
3721
3749
|
// Modal en ese momento en vez de montar un WebView en blanco.
|
|
@@ -3726,6 +3754,11 @@ ${REVEAL_JS}
|
|
|
3726
3754
|
|
|
3727
3755
|
function setLoading(isLoading){
|
|
3728
3756
|
spinner.style.display=isLoading?'flex':'none';
|
|
3757
|
+
// El spinner no tapa el survey (28px en posicion absoluta), asi que sin esto el usuario
|
|
3758
|
+
// puede seguir cambiando de opcion mientras se envia la pagina, y ese cambio ya no viaja
|
|
3759
|
+
// con ella. Se bloquea el wrapper, que es el elemento estable: el div de dentro lo
|
|
3760
|
+
// sustituye @magicfeedback/native por su propio contenedor al generar el survey.
|
|
3761
|
+
ddSetSurveyBusy(formWrapper, isLoading);
|
|
3729
3762
|
if(!isLoading){
|
|
3730
3763
|
formHost.style.visibility='visible';
|
|
3731
3764
|
// Fin de la carga, sea por survey cargado o por error. Entre p\xE1ginas es no-op: la
|
|
@@ -5508,6 +5541,9 @@ var DeepdotsPopups = class {
|
|
|
5508
5541
|
this.emitEvent("popup_shown", def.surveyId, { popupId: def.id });
|
|
5509
5542
|
}
|
|
5510
5543
|
shouldShow(def, pathUrl, skipPathCheck = false) {
|
|
5544
|
+
if (this.isPathExcluded(def, pathUrl)) {
|
|
5545
|
+
return false;
|
|
5546
|
+
}
|
|
5511
5547
|
if (!skipPathCheck && !this.matchesSegmentsPath(def, pathUrl)) {
|
|
5512
5548
|
return false;
|
|
5513
5549
|
}
|
|
@@ -5538,40 +5574,85 @@ var DeepdotsPopups = class {
|
|
|
5538
5574
|
}
|
|
5539
5575
|
return matches;
|
|
5540
5576
|
}
|
|
5577
|
+
/** `segments.path`: rutas donde el popup PUEDE mostrarse. Sin lista, en todas. */
|
|
5541
5578
|
matchesSegmentsPath(def, pathUrl) {
|
|
5542
5579
|
const paths = def.segments?.path;
|
|
5543
|
-
if (!paths || paths.length === 0) return true;
|
|
5544
|
-
|
|
5580
|
+
if (!Array.isArray(paths) || paths.length === 0) return true;
|
|
5581
|
+
const location = this.resolveCurrentLocation(pathUrl);
|
|
5582
|
+
if (!location) {
|
|
5545
5583
|
this.debug("No window.location available for path comparison", { popupId: def.id, paths });
|
|
5546
5584
|
return true;
|
|
5547
5585
|
}
|
|
5548
|
-
const normalizedHref = this.normalizeUrl(pathUrl || window.location.href || "");
|
|
5549
|
-
const currentUrl = this.safeParseUrl(normalizedHref);
|
|
5550
|
-
const normalizedPath = this.normalizeUrl(currentUrl?.pathname || window.location.pathname || "");
|
|
5551
5586
|
const matches = paths.some((rawCandidate) => {
|
|
5552
|
-
const
|
|
5553
|
-
let match = false;
|
|
5554
|
-
if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
|
|
5555
|
-
match = normalizedHref === candidate;
|
|
5556
|
-
} else if (candidate.startsWith("/")) {
|
|
5557
|
-
match = normalizedHref.includes(candidate);
|
|
5558
|
-
} else {
|
|
5559
|
-
match = normalizedPath === candidate;
|
|
5560
|
-
}
|
|
5587
|
+
const match = this.matchesPathCandidate(rawCandidate, location);
|
|
5561
5588
|
this.debug("Path comparison", {
|
|
5562
5589
|
popupId: def.id,
|
|
5563
|
-
candidate,
|
|
5564
|
-
currentPath:
|
|
5565
|
-
currentHref:
|
|
5590
|
+
candidate: rawCandidate,
|
|
5591
|
+
currentPath: location.path,
|
|
5592
|
+
currentHref: location.href,
|
|
5566
5593
|
match
|
|
5567
5594
|
});
|
|
5568
5595
|
return match;
|
|
5569
5596
|
});
|
|
5570
5597
|
if (!matches) {
|
|
5571
|
-
this.debug("No path match for popup", { popupId: def.id, paths, currentPath:
|
|
5598
|
+
this.debug("No path match for popup", { popupId: def.id, paths, currentPath: location.path });
|
|
5572
5599
|
}
|
|
5573
5600
|
return matches;
|
|
5574
5601
|
}
|
|
5602
|
+
/**
|
|
5603
|
+
* `segments.excludedPaths`: rutas donde el popup NO debe mostrarse. Gana sobre
|
|
5604
|
+
* `segments.path` (`path: ['/']` + `excludedPaths: ['/cart']` = en todas menos el
|
|
5605
|
+
* carrito) y se aplica también cuando no hay `path` (= en todas menos las excluidas).
|
|
5606
|
+
*/
|
|
5607
|
+
isPathExcluded(def, pathUrl) {
|
|
5608
|
+
const excluded = def.segments?.excludedPaths;
|
|
5609
|
+
if (!Array.isArray(excluded) || excluded.length === 0) return false;
|
|
5610
|
+
const location = this.resolveCurrentLocation(pathUrl);
|
|
5611
|
+
if (!location) {
|
|
5612
|
+
this.debug("No window.location available for excluded path comparison", { popupId: def.id, excluded });
|
|
5613
|
+
return false;
|
|
5614
|
+
}
|
|
5615
|
+
const hit = excluded.find((rawCandidate) => this.matchesPathCandidate(rawCandidate, location));
|
|
5616
|
+
if (hit !== void 0) {
|
|
5617
|
+
this.debug("Popup excluded by path", {
|
|
5618
|
+
popupId: def.id,
|
|
5619
|
+
candidate: hit,
|
|
5620
|
+
currentPath: location.path,
|
|
5621
|
+
currentHref: location.href
|
|
5622
|
+
});
|
|
5623
|
+
return true;
|
|
5624
|
+
}
|
|
5625
|
+
return false;
|
|
5626
|
+
}
|
|
5627
|
+
/**
|
|
5628
|
+
* Compara UN candidato de `segments.path`/`segments.excludedPaths` con la ruta
|
|
5629
|
+
* actual. Mismas reglas para incluir y para excluir:
|
|
5630
|
+
* - URL absoluta → href completo exacto
|
|
5631
|
+
* - empieza por / → subcadena del href (así entran las rutas con hash: `/#/home`)
|
|
5632
|
+
* - resto → pathname exacto
|
|
5633
|
+
* Ignora entradas que no sean string: el backend puede colar un `null` en la lista
|
|
5634
|
+
* y no puede tumbar la evaluación del trigger entero (mismo fallo que hubo con
|
|
5635
|
+
* `segments.lang`).
|
|
5636
|
+
*/
|
|
5637
|
+
matchesPathCandidate(rawCandidate, location) {
|
|
5638
|
+
if (typeof rawCandidate !== "string") return false;
|
|
5639
|
+
const candidate = this.normalizeUrl(rawCandidate);
|
|
5640
|
+
if (!candidate) return false;
|
|
5641
|
+
if (candidate.startsWith("http://") || candidate.startsWith("https://")) {
|
|
5642
|
+
return location.href === candidate;
|
|
5643
|
+
}
|
|
5644
|
+
if (candidate.startsWith("/")) {
|
|
5645
|
+
return location.href.includes(candidate);
|
|
5646
|
+
}
|
|
5647
|
+
return location.path === candidate;
|
|
5648
|
+
}
|
|
5649
|
+
/** href + pathname normalizados de la ruta a evaluar, o null si no hay `window.location`. */
|
|
5650
|
+
resolveCurrentLocation(pathUrl) {
|
|
5651
|
+
if (typeof window === "undefined" || !window.location) return null;
|
|
5652
|
+
const href = this.normalizeUrl(pathUrl || window.location.href || "");
|
|
5653
|
+
const parsed = this.safeParseUrl(href);
|
|
5654
|
+
return { href, path: this.normalizeUrl(parsed?.pathname || window.location.pathname || "") };
|
|
5655
|
+
}
|
|
5575
5656
|
evaluateCooldown(def, condition) {
|
|
5576
5657
|
switch (condition.answered) {
|
|
5577
5658
|
case "SHOWED":
|