@magicfeedback/popup-sdk 1.14.0 → 1.16.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.
@@ -15,7 +15,7 @@ import {
15
15
  sdkWarn,
16
16
  setSurveyBusy,
17
17
  style_default
18
- } from "./chunk-C7VD3HY4.mjs";
18
+ } from "./chunk-AFRHPS3K.mjs";
19
19
 
20
20
  // node_modules/@magicfeedback/native/dist/magicfeedback-sdk.browser.js
21
21
  var require_magicfeedback_sdk_browser = __commonJS({
@@ -2868,31 +2868,36 @@ function insertPopupLogo(parent, anchor, style, id) {
2868
2868
 
2869
2869
  // src/ui/renderPopup.ts
2870
2870
  var import_native = __toESM(require_magicfeedback_sdk_browser());
2871
- function ensureMagicFeedbackStyles(_popup) {
2872
- const STYLE_ID = "magicfeedback-sdk-styles";
2873
- if (document.getElementById(STYLE_ID)) return;
2874
- const style = document.createElement("style");
2875
- style.id = STYLE_ID;
2876
- style.textContent = style_default;
2877
- document.head.appendChild(style);
2871
+ function ensureStyle(id, css, nonce) {
2872
+ let el = document.getElementById(id);
2873
+ if (el && nonce && el.getAttribute("nonce") !== nonce) {
2874
+ el.remove();
2875
+ el = null;
2876
+ }
2877
+ if (!el) {
2878
+ el = document.createElement("style");
2879
+ el.id = id;
2880
+ if (nonce) el.setAttribute("nonce", nonce);
2881
+ el.textContent = css;
2882
+ document.head.appendChild(el);
2883
+ } else if (el.textContent !== css) {
2884
+ el.textContent = css;
2885
+ }
2886
+ return el;
2887
+ }
2888
+ function ensureMagicFeedbackStyles(nonce) {
2889
+ ensureStyle("magicfeedback-sdk-styles", style_default, nonce);
2878
2890
  }
2879
2891
  var SURVEY_ALIGNMENT_STYLE_ID = "deepdots-survey-alignment";
2880
- function ensureSurveyAlignmentStyles() {
2881
- if (document.getElementById(SURVEY_ALIGNMENT_STYLE_ID)) return;
2882
- const style = document.createElement("style");
2883
- style.id = SURVEY_ALIGNMENT_STYLE_ID;
2884
- style.textContent = `
2892
+ function ensureSurveyAlignmentStyles(nonce) {
2893
+ ensureStyle(SURVEY_ALIGNMENT_STYLE_ID, `
2885
2894
  .deepdots-popup .magicfeedback-container,
2886
2895
  .deepdots-popup .magicfeedback-form,
2887
2896
  .deepdots-popup .magicfeedback-div { padding-left: 0; padding-right: 0; }
2888
- `;
2889
- document.head.appendChild(style);
2897
+ `, nonce);
2890
2898
  }
2891
- function ensureSpinnerStyles(_popup) {
2892
- if (document.getElementById("deepdots-spinner-styles")) return;
2893
- const style = document.createElement("style");
2894
- style.id = "deepdots-spinner-styles";
2895
- style.textContent = `
2899
+ function ensureSpinnerStyles(nonce) {
2900
+ ensureStyle("deepdots-spinner-styles", `
2896
2901
  /* El enunciado trae margin-top:20px del CSS de surveys, que sumaba al hueco de la barra
2897
2902
  de progreso y descompensaba la simetr\xEDa. Solo se anula en el primero: entre preguntas
2898
2903
  de la misma p\xE1gina sigue separando. */
@@ -2900,14 +2905,10 @@ function ensureSpinnerStyles(_popup) {
2900
2905
  @keyframes ddspin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
2901
2906
  .mf-spinner { display:flex; justify-content:center; align-items:center; padding:8px 0; }
2902
2907
  .mf-spinner-circle { width:28px; height:28px; border:3px solid #e0e6ed; border-top-color:#1E293B; border-radius:50%; animation: ddspin 0.9s linear infinite; }
2903
- `;
2904
- document.head.appendChild(style);
2908
+ `, nonce);
2905
2909
  }
2906
- function ensureResponsiveStyles(_popup) {
2907
- if (document.getElementById("deepdots-responsive-styles")) return;
2908
- const style = document.createElement("style");
2909
- style.id = "deepdots-responsive-styles";
2910
- style.textContent = `
2910
+ function ensureResponsiveStyles(nonce) {
2911
+ ensureStyle("deepdots-responsive-styles", `
2911
2912
  /* Responsive adjustments */
2912
2913
  @media (max-width: 640px) {
2913
2914
  .deepdots-popup {
@@ -2940,32 +2941,20 @@ function ensureResponsiveStyles(_popup) {
2940
2941
  overflow-y: auto !important;
2941
2942
  }
2942
2943
  }
2943
- `;
2944
- document.head.appendChild(style);
2944
+ `, nonce);
2945
2945
  }
2946
- function ensureCustomCss(css) {
2946
+ function ensureCustomCss(css, nonce) {
2947
2947
  const STYLE_ID = "deepdots-custom-css";
2948
- const existing = document.getElementById(STYLE_ID);
2949
2948
  if (!css) {
2950
- existing?.remove();
2949
+ document.getElementById(STYLE_ID)?.remove();
2951
2950
  return;
2952
2951
  }
2953
- const el = existing ?? document.createElement("style");
2954
- el.id = STYLE_ID;
2955
- if (el.textContent !== css) el.textContent = css;
2956
- document.head.appendChild(el);
2952
+ document.head.appendChild(ensureStyle(STYLE_ID, css, nonce));
2957
2953
  }
2958
- function ensureFontFace(family, url) {
2954
+ function ensureFontFace(family, url, nonce) {
2959
2955
  const css = buildFontFaceCss(family, url);
2960
2956
  if (!css) return;
2961
- const STYLE_ID = "deepdots-font-face";
2962
- let el = document.getElementById(STYLE_ID);
2963
- if (!el) {
2964
- el = document.createElement("style");
2965
- el.id = STYLE_ID;
2966
- document.head.appendChild(el);
2967
- }
2968
- if (el.textContent !== css) el.textContent = css;
2957
+ ensureStyle("deepdots-font-face", css, nonce);
2969
2958
  }
2970
2959
  function hasFinePointer() {
2971
2960
  return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(pointer: fine)").matches;
@@ -2975,6 +2964,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
2975
2964
  let stylesInjected = false;
2976
2965
  let pageDepth = 0;
2977
2966
  let onStartPage = false;
2967
+ const cspNonce = options?.cspNonce?.trim() || void 0;
2978
2968
  let labels = getLabels(options?.language);
2979
2969
  let actionLabels = resolveActionLabels(actions, options?.language);
2980
2970
  let direction = directionFor(options?.language);
@@ -3026,7 +3016,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3026
3016
  popup.style.fontFamily = familyValue;
3027
3017
  popup.style.setProperty("--deepdots-font", familyValue);
3028
3018
  popup.classList.add("deepdots-has-font");
3029
- if (font.url) ensureFontFace(font.family, font.url);
3019
+ if (font.url) ensureFontFace(font.family, font.url, cspNonce);
3030
3020
  }
3031
3021
  const header = document.createElement("div");
3032
3022
  header.className = "deepdots-popup-header";
@@ -3075,10 +3065,11 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3075
3065
  closeBtn.style.color = theme.textPrimary;
3076
3066
  closeBtn.style.transform = "scale(1)";
3077
3067
  };
3078
- closeBtn.onclick = () => {
3068
+ const closeFromChrome = () => {
3079
3069
  emit("popup_clicked", surveyId, { action: "close_icon" });
3080
3070
  onClose();
3081
3071
  };
3072
+ closeBtn.onclick = closeFromChrome;
3082
3073
  closeBtn.style.flex = "0 0 auto";
3083
3074
  closeBtn.style.marginLeft = "auto";
3084
3075
  header.appendChild(closeBtn);
@@ -3142,11 +3133,11 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3142
3133
  }
3143
3134
  progressFollowUp.style.display = p.followup ? "inline-block" : "none";
3144
3135
  }
3145
- ensureMagicFeedbackStyles(popup);
3146
- ensureSurveyAlignmentStyles();
3147
- ensureSpinnerStyles(popup);
3148
- ensureResponsiveStyles(popup);
3149
- ensureCustomCss(options?.surveyCss);
3136
+ ensureMagicFeedbackStyles(cspNonce);
3137
+ ensureSurveyAlignmentStyles(cspNonce);
3138
+ ensureSpinnerStyles(cspNonce);
3139
+ ensureResponsiveStyles(cspNonce);
3140
+ ensureCustomCss(options?.surveyCss, cspNonce);
3150
3141
  const containerContent = document.createElement("div");
3151
3142
  containerContent.id = "dd-content";
3152
3143
  containerContent.className = "deepdots-popup-container-content";
@@ -3186,6 +3177,12 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3186
3177
  formWrapper.appendChild(spinnerEl);
3187
3178
  formWrapper.appendChild(formHost);
3188
3179
  main.appendChild(formWrapper);
3180
+ const loadErrorEl = document.createElement("div");
3181
+ loadErrorEl.id = "dd-load-error";
3182
+ loadErrorEl.className = "deepdots-load-error";
3183
+ loadErrorEl.setAttribute("role", "alert");
3184
+ loadErrorEl.style.cssText = `display:none; width:100%; text-align:center; padding:24px 0; font-size:15px; color:${theme.textPrimary};`;
3185
+ main.appendChild(loadErrorEl);
3189
3186
  main.appendChild(errorHint);
3190
3187
  const footer = document.createElement("div");
3191
3188
  footer.id = "dd-footer";
@@ -3301,6 +3298,13 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3301
3298
  justify-content: center;
3302
3299
  text-align: center;
3303
3300
  `;
3301
+ const cancelButton = document.createElement("button");
3302
+ cancelButton.id = "dd-cancel";
3303
+ cancelButton.type = "button";
3304
+ cancelButton.className = "dd-nav-btn";
3305
+ cancelButton.textContent = actionLabels.decline;
3306
+ cancelButton.style.cssText = submitButton.style.cssText;
3307
+ cancelButton.onclick = closeFromChrome;
3304
3308
  submitButton.onclick = () => {
3305
3309
  if (!surveyCompletedEmitted) {
3306
3310
  emit("popup_clicked", surveyId, { action: "manual_send" });
@@ -3314,6 +3318,8 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3314
3318
  startButton.textContent = actionLabels.start;
3315
3319
  closeButton.textContent = actionLabels.complete;
3316
3320
  submitButton.textContent = actionLabels.accept;
3321
+ cancelButton.textContent = actionLabels.decline;
3322
+ loadErrorEl.textContent = labels.errorLoad;
3317
3323
  closeBtn.setAttribute("aria-label", labels.closeAria);
3318
3324
  spinnerEl.setAttribute("aria-label", labels.loadingAria);
3319
3325
  progressFollowUp.textContent = labels.followUp;
@@ -3324,10 +3330,12 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3324
3330
  startButton.style.display = "none";
3325
3331
  submitButton.style.display = "none";
3326
3332
  closeButton.style.display = "none";
3333
+ cancelButton.style.display = "none";
3327
3334
  footer.appendChild(submitButton);
3328
3335
  footer.appendChild(backButton);
3329
3336
  footer.appendChild(closeButton);
3330
3337
  footer.appendChild(startButton);
3338
+ footer.appendChild(cancelButton);
3331
3339
  containerContent.appendChild(main);
3332
3340
  footer.style.flex = "0 0 auto";
3333
3341
  containerContent.appendChild(footer);
@@ -3336,6 +3344,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3336
3344
  startButton.style.display = "none";
3337
3345
  submitButton.style.display = "none";
3338
3346
  closeButton.style.display = "none";
3347
+ cancelButton.style.display = "none";
3339
3348
  backButton.style.width = "";
3340
3349
  startButton.style.width = "";
3341
3350
  submitButton.style.width = "";
@@ -3365,6 +3374,9 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3365
3374
  case "error":
3366
3375
  setLoading(false);
3367
3376
  break;
3377
+ case "load_error":
3378
+ cancelButton.style.display = "inline-flex";
3379
+ break;
3368
3380
  }
3369
3381
  }
3370
3382
  function updateNavButtons() {
@@ -3386,6 +3398,20 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3386
3398
  img.style.cssText = "max-width:100%; height:auto; margin:0 auto 16px auto; display:block;";
3387
3399
  });
3388
3400
  }
3401
+ let loadFailed = false;
3402
+ function showLoadError(reason) {
3403
+ sdkWarn("[Deepdots] survey failed to load:", reason);
3404
+ if (loadFailed) return;
3405
+ loadFailed = true;
3406
+ progressEl.style.display = "none";
3407
+ formWrapper.style.display = "none";
3408
+ errorHint.style.display = "none";
3409
+ loadErrorEl.textContent = labels.errorLoad;
3410
+ loadErrorEl.style.display = "block";
3411
+ setLoading(false);
3412
+ updateButtons("load_error");
3413
+ reveal();
3414
+ }
3389
3415
  popup.appendChild(header);
3390
3416
  popup.appendChild(progressEl);
3391
3417
  popup.appendChild(containerContent);
@@ -3450,7 +3476,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3450
3476
  try {
3451
3477
  if (!import_native.default || typeof import_native.default.form !== "function") {
3452
3478
  sdkWarn("[MagicFeedback] form() no disponible. Fallback manual.");
3453
- setLoading(false);
3479
+ showLoadError("form() not available");
3454
3480
  return;
3455
3481
  }
3456
3482
  import_native.default.init(
@@ -3476,7 +3502,11 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3476
3502
  // quitado el `inert`. La apertura va aparte (ver autofocusOnOpen).
3477
3503
  autofocus: "navigation"
3478
3504
  };
3479
- generateOptions.onLoadedEvent = ({ formData, lang }) => {
3505
+ generateOptions.onLoadedEvent = ({ formData, lang, error }) => {
3506
+ if (error) {
3507
+ showLoadError(error);
3508
+ return;
3509
+ }
3480
3510
  const shownLang = typeof lang === "string" && lang.trim().length > 0 ? lang : void 0;
3481
3511
  const surveyLang = shownLang ?? (Array.isArray(formData?.lang) ? formData.lang.find((l) => typeof l === "string" && l.trim().length > 0) : void 0);
3482
3512
  if (surveyLang) applyLabels(surveyLang);
@@ -3575,11 +3605,11 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3575
3605
  };
3576
3606
  formInstance.generate(formDivId, generateOptions).catch((err) => {
3577
3607
  sdkError("[MagicFeedback] Error generating form:", err);
3578
- setLoading(false);
3608
+ showLoadError(err);
3579
3609
  });
3580
3610
  } catch (e) {
3581
3611
  sdkError("[MagicFeedback] Exception initializing form:", e);
3582
- setLoading(false);
3612
+ showLoadError(e);
3583
3613
  }
3584
3614
  }
3585
3615
  export {
@@ -3587,4 +3617,4 @@ export {
3587
3617
  SURVEY_ALIGNMENT_STYLE_ID,
3588
3618
  renderPopup
3589
3619
  };
3590
- //# sourceMappingURL=renderPopup-Z6TENBP6.mjs.map
3620
+ //# sourceMappingURL=renderPopup-YCAQ3ODC.mjs.map