@magicfeedback/popup-sdk 1.7.1 → 1.7.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/README.md +33 -0
- package/dist/{chunk-WNIUIOKF.mjs → chunk-322DDMX6.mjs} +69 -1
- package/dist/chunk-322DDMX6.mjs.map +1 -0
- package/dist/{chunk-W6MPSWMS.mjs → chunk-XHR3MHJO.mjs} +69 -1
- package/dist/chunk-XHR3MHJO.mjs.map +1 -0
- package/dist/index.d.mts +74 -6
- package/dist/index.d.ts +74 -6
- package/dist/index.js +257 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +137 -10
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.d.mts +41 -5
- package/dist/react-native.d.ts +41 -5
- package/dist/react-native.js +272 -22
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +153 -20
- package/dist/react-native.mjs.map +1 -1
- package/dist/{renderPopup-HHQMAW3G.mjs → renderPopup-5QXL6EJW.mjs} +46 -6
- package/dist/renderPopup-5QXL6EJW.mjs.map +1 -0
- package/dist/{renderPopup-EWGKG53W.mjs → renderPopup-SNDPX5RX.mjs} +46 -6
- package/dist/renderPopup-SNDPX5RX.mjs.map +1 -0
- package/package.json +4 -3
- package/dist/chunk-W6MPSWMS.mjs.map +0 -1
- package/dist/chunk-WNIUIOKF.mjs.map +0 -1
- package/dist/renderPopup-EWGKG53W.mjs.map +0 -1
- package/dist/renderPopup-HHQMAW3G.mjs.map +0 -1
package/dist/react-native.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
LABELS,
|
|
3
|
+
PRIMARY_COLOR_JS,
|
|
3
4
|
RESOLVE_LOCALE_JS,
|
|
5
|
+
REVEAL_TIMEOUT_MS,
|
|
4
6
|
RTL_LOCALES,
|
|
5
7
|
STORAGE_KEYS,
|
|
6
8
|
TrackingManager,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
sdkWarn,
|
|
16
18
|
setLogger,
|
|
17
19
|
style_default
|
|
18
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-322DDMX6.mjs";
|
|
19
21
|
|
|
20
22
|
// src/react-native/index.tsx
|
|
21
23
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
@@ -211,6 +213,30 @@ function resolveEnvironment(nodeEnv) {
|
|
|
211
213
|
}
|
|
212
214
|
|
|
213
215
|
// src/ui/surveyHtml.ts
|
|
216
|
+
var REVEAL_JS = `
|
|
217
|
+
function ddCreateReveal(popup, onReveal, timeoutMs){
|
|
218
|
+
var revealed=false, timer=null;
|
|
219
|
+
function reveal(){
|
|
220
|
+
if(revealed){ return; }
|
|
221
|
+
revealed=true;
|
|
222
|
+
if(timer){ clearTimeout(timer); timer=null; }
|
|
223
|
+
onReveal();
|
|
224
|
+
}
|
|
225
|
+
function revealWhenPainted(){
|
|
226
|
+
if(revealed){ return; }
|
|
227
|
+
var imgs=popup.querySelectorAll('img'), pending=[];
|
|
228
|
+
for(var i=0;i<imgs.length;i++){ if(!imgs[i].complete){ pending.push(imgs[i]); } }
|
|
229
|
+
if(!pending.length){ reveal(); return; }
|
|
230
|
+
var left=pending.length;
|
|
231
|
+
function onSettled(){ left--; if(left<=0){ reveal(); } }
|
|
232
|
+
for(var j=0;j<pending.length;j++){
|
|
233
|
+
pending[j].addEventListener('load', onSettled);
|
|
234
|
+
pending[j].addEventListener('error', onSettled);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
timer=setTimeout(reveal, timeoutMs);
|
|
238
|
+
return { reveal: reveal, whenPainted: revealWhenPainted };
|
|
239
|
+
}`;
|
|
214
240
|
var POSITION_MAP = {
|
|
215
241
|
center: { justifyContent: "center", alignItems: "center", padding: "0", background: "rgba(0,0,0,0.5)" },
|
|
216
242
|
bottom: { justifyContent: "center", alignItems: "flex-end", padding: "16px", background: "transparent" },
|
|
@@ -284,7 +310,13 @@ function buildSurveyHtml(opts) {
|
|
|
284
310
|
${style_default}
|
|
285
311
|
${fontFaceCss}
|
|
286
312
|
html,body{margin:0;padding:0;height:100%;font-family:${fontFamilyValue}}
|
|
287
|
-
|
|
313
|
+
/* Apertura diferida: ni la tarjeta ni el velo se pintan hasta que el survey est\xE1 listo
|
|
314
|
+
(\`dd-ready\`). Si el fondo entrara antes, en RN se ver\xEDa el velo oscuro varios cientos de ms
|
|
315
|
+
antes que el contenido, que es la misma mala sensaci\xF3n que el spinner. */
|
|
316
|
+
body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${pos.alignItems};background:transparent;padding:${bodyPadding};box-sizing:border-box}
|
|
317
|
+
body.dd-ready{background:${bodyBg}}
|
|
318
|
+
#dd-popup{visibility:hidden}
|
|
319
|
+
body.dd-ready #dd-popup{visibility:visible}
|
|
288
320
|
.deepdots-popup{position:relative;display:flex;flex-direction:column;justify-content:flex-start;background:${cardBg};color-scheme:${colorScheme};border-radius:${cardRadius};padding:24px;box-shadow:${cardShadow};max-width:${cardMaxWidth};width:${cardWidth};min-height:${cardMinHeight};height:${cardHeight};max-height:${cardMaxHeight};box-sizing:border-box}
|
|
289
321
|
.deepdots-popup-header{display:flex;justify-content:space-between;align-items:center;gap:12px;width:100%;flex:0 0 auto}
|
|
290
322
|
/* Neutraliza la regla \`.deepdots-popup h2\` del CSS del survey (uppercase, centrado y
|
|
@@ -318,6 +350,13 @@ body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${
|
|
|
318
350
|
#dd-form-wrapper{width:100%;flex:1 1 auto}
|
|
319
351
|
#mf{width:100%;box-sizing:border-box;visibility:hidden}
|
|
320
352
|
.deepdots-popup-main *{max-width:100%;box-sizing:border-box}
|
|
353
|
+
/* El margen lateral lo pone la tarjeta: el CSS del survey lo a\xF1ade otra vez en el contenedor, en
|
|
354
|
+
el formulario y en el bloque de cada pregunta, y eso deja el enunciado y las opciones m\xE1s
|
|
355
|
+
adentro que el logo, el t\xEDtulo y la barra de progreso. Solo el lateral; el vertical separa las
|
|
356
|
+
preguntas. Mismas reglas que en el popup DOM (renderPopup.ts). */
|
|
357
|
+
.deepdots-popup .magicfeedback-container,
|
|
358
|
+
.deepdots-popup .magicfeedback-form,
|
|
359
|
+
.deepdots-popup .magicfeedback-div{padding-left:0;padding-right:0}
|
|
321
360
|
#dd-logo{max-height:40px;max-width:100%;object-fit:contain;display:block;margin:12px 0 0 0}
|
|
322
361
|
.deepdots-error-hint{display:none;margin:12px 0 0 0;padding:10px 12px;border-radius:6px;background:#FEF3C7;color:#92400E;border:1px solid #FCD34D;font-size:13px}
|
|
323
362
|
/* Pantalla final: el HTML del editor de la plataforma (imagen + texto), centrado. */
|
|
@@ -325,7 +364,7 @@ body{display:${bodyDisplay};justify-content:${pos.justifyContent};align-items:${
|
|
|
325
364
|
.deepdots-success img{max-width:100%;height:auto;margin:0 auto 16px auto;display:block}
|
|
326
365
|
.deepdots-success p{margin:0;font-size:16px;font-weight:600;line-height:1.4}
|
|
327
366
|
.deepdots-popup-footer{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:4px;margin-top:auto;width:100%;padding-top:12px}
|
|
328
|
-
.dd-nav-btn{display:none;border:none;min-height:44px;padding:12px 24px;border-radius:
|
|
367
|
+
.dd-nav-btn{display:none;border:none;min-height:44px;padding:12px 24px;border-radius:999px;cursor:pointer;font-size:15px;font-weight:600;align-items:center;justify-content:center;text-align:center}
|
|
329
368
|
/* Secundario como bot\xF3n de texto: sin borde ni fondo, para que el primario sea la \xFAnica CTA. */
|
|
330
369
|
#dd-back{background:transparent;color:${textMuted};border:none}
|
|
331
370
|
#dd-start,#dd-complete,#dd-submit{background:#1E293B;color:#fff;border:none}
|
|
@@ -550,9 +589,23 @@ ${customCss}
|
|
|
550
589
|
}
|
|
551
590
|
}
|
|
552
591
|
|
|
592
|
+
${PRIMARY_COLOR_JS}
|
|
593
|
+
${REVEAL_JS}
|
|
594
|
+
// El popup se ense\xF1a cuando el survey est\xE1 pintado; \`ready\` deja al host abrir su propio
|
|
595
|
+
// Modal en ese momento en vez de montar un WebView en blanco.
|
|
596
|
+
var ddReveal=ddCreateReveal(popup, function(){
|
|
597
|
+
document.body.classList.add('dd-ready');
|
|
598
|
+
emitJSON('ready');
|
|
599
|
+
}, ${REVEAL_TIMEOUT_MS});
|
|
600
|
+
|
|
553
601
|
function setLoading(isLoading){
|
|
554
602
|
spinner.style.display=isLoading?'flex':'none';
|
|
555
|
-
if(!isLoading){
|
|
603
|
+
if(!isLoading){
|
|
604
|
+
formHost.style.visibility='visible';
|
|
605
|
+
// Fin de la carga, sea por survey cargado o por error. Entre p\xE1ginas es no-op: la
|
|
606
|
+
// revelaci\xF3n solo act\xFAa la primera vez.
|
|
607
|
+
ddReveal.whenPainted();
|
|
608
|
+
}
|
|
556
609
|
footer.style.display=isLoading?'none':'flex';
|
|
557
610
|
backBtn.disabled=isLoading; startBtn.disabled=isLoading; completeBtn.disabled=isLoading; submitBtn.disabled=isLoading;
|
|
558
611
|
if(isLoading){ updateButtons(null); }
|
|
@@ -595,6 +648,10 @@ ${customCss}
|
|
|
595
648
|
if(s.loadingBarColor){ progressBar.style.background=s.loadingBarColor; progressFollowUp.style.background=s.loadingBarColor; }
|
|
596
649
|
if(chromeOn && s.boxBackgroundColor){ popup.style.background=s.boxBackgroundColor; }
|
|
597
650
|
if(s.contentAlign){ main.style.justifyContent = s.contentAlign==='center' ? 'center' : 'flex-start'; }
|
|
651
|
+
// El survey pinta sus controles con --mf-primary, que sale de primaryColor; si la
|
|
652
|
+
// integraci\xF3n solo configura el del bot\xF3n, el popup mezclar\xEDa el color de la marca
|
|
653
|
+
// con el gris azulado por defecto del paquete.
|
|
654
|
+
ddApplySurveyPrimaryColor(popup, s);
|
|
598
655
|
if(s.buttonPrimaryColor){
|
|
599
656
|
submitBtn.style.background=s.buttonPrimaryColor; submitBtn.style.border='none'; submitBtn.style.color='#fff';
|
|
600
657
|
startBtn.style.background=s.buttonPrimaryColor; startBtn.style.border='none'; startBtn.style.color='#fff';
|
|
@@ -686,6 +743,7 @@ ${customCss}
|
|
|
686
743
|
}
|
|
687
744
|
|
|
688
745
|
// src/platform/react-native-renderer.ts
|
|
746
|
+
var NATIVE_READY_GRACE_MS = 500;
|
|
689
747
|
var ReactNativePopupRenderer = class {
|
|
690
748
|
constructor(options = {}) {
|
|
691
749
|
this.options = options;
|
|
@@ -693,6 +751,8 @@ var ReactNativePopupRenderer = class {
|
|
|
693
751
|
this.onCloseFn = null;
|
|
694
752
|
this.currentSurveyId = null;
|
|
695
753
|
this.partialEmitted = false;
|
|
754
|
+
this.readyEmitted = false;
|
|
755
|
+
this.readyTimer = null;
|
|
696
756
|
}
|
|
697
757
|
init() {
|
|
698
758
|
}
|
|
@@ -701,6 +761,8 @@ var ReactNativePopupRenderer = class {
|
|
|
701
761
|
this.onCloseFn = onClose;
|
|
702
762
|
this.currentSurveyId = surveyId;
|
|
703
763
|
this.partialEmitted = false;
|
|
764
|
+
this.readyEmitted = false;
|
|
765
|
+
this.armReadyFallback(surveyId);
|
|
704
766
|
const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
|
|
705
767
|
const html = buildSurveyHtml({
|
|
706
768
|
surveyId,
|
|
@@ -728,9 +790,32 @@ var ReactNativePopupRenderer = class {
|
|
|
728
790
|
}
|
|
729
791
|
}
|
|
730
792
|
hide() {
|
|
793
|
+
this.clearReadyFallback();
|
|
731
794
|
this.options.onHide?.();
|
|
732
795
|
this.currentSurveyId = null;
|
|
733
796
|
}
|
|
797
|
+
/** Respaldo del aviso de listo por si el WebView no llega a ejecutar el HTML. */
|
|
798
|
+
armReadyFallback(surveyId) {
|
|
799
|
+
this.clearReadyFallback();
|
|
800
|
+
if (!this.options.onReady) return;
|
|
801
|
+
this.readyTimer = setTimeout(() => {
|
|
802
|
+
this.readyTimer = null;
|
|
803
|
+
this.emitReady(surveyId);
|
|
804
|
+
}, REVEAL_TIMEOUT_MS + NATIVE_READY_GRACE_MS);
|
|
805
|
+
}
|
|
806
|
+
clearReadyFallback() {
|
|
807
|
+
if (this.readyTimer !== null) {
|
|
808
|
+
clearTimeout(this.readyTimer);
|
|
809
|
+
this.readyTimer = null;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
/** Idempotente: el WebView puede avisar a la vez que vence el respaldo. */
|
|
813
|
+
emitReady(surveyId) {
|
|
814
|
+
if (this.readyEmitted) return;
|
|
815
|
+
this.readyEmitted = true;
|
|
816
|
+
this.clearReadyFallback();
|
|
817
|
+
this.options.onReady?.({ surveyId });
|
|
818
|
+
}
|
|
734
819
|
/**
|
|
735
820
|
* El host la conecta al `onMessage` del WebView. Traduce los mensajes del survey a
|
|
736
821
|
* eventos del SDK: primera interacción → `popup_clicked` (PARTIAL), completado →
|
|
@@ -746,6 +831,9 @@ var ReactNativePopupRenderer = class {
|
|
|
746
831
|
name = raw;
|
|
747
832
|
}
|
|
748
833
|
switch (name) {
|
|
834
|
+
case "ready":
|
|
835
|
+
this.emitReady(surveyId);
|
|
836
|
+
break;
|
|
749
837
|
case "loaded":
|
|
750
838
|
case "before_submit":
|
|
751
839
|
case "after_submit":
|
|
@@ -773,6 +861,33 @@ function createReactNativeRenderer() {
|
|
|
773
861
|
return new ReactNativePopupRenderer();
|
|
774
862
|
}
|
|
775
863
|
|
|
864
|
+
// src/ui/preload.ts
|
|
865
|
+
var defaultLoader = () => import("./renderPopup-SNDPX5RX.mjs");
|
|
866
|
+
var pending = null;
|
|
867
|
+
function preloadRenderPopup(loader = defaultLoader) {
|
|
868
|
+
if (pending) return pending;
|
|
869
|
+
try {
|
|
870
|
+
pending = loader().then(() => void 0).catch(() => {
|
|
871
|
+
pending = null;
|
|
872
|
+
});
|
|
873
|
+
} catch {
|
|
874
|
+
pending = null;
|
|
875
|
+
return Promise.resolve();
|
|
876
|
+
}
|
|
877
|
+
return pending;
|
|
878
|
+
}
|
|
879
|
+
function schedulePreloadRenderPopup(loader) {
|
|
880
|
+
const run = () => {
|
|
881
|
+
void preloadRenderPopup(loader);
|
|
882
|
+
};
|
|
883
|
+
const idle = globalThis.requestIdleCallback;
|
|
884
|
+
if (typeof idle === "function") {
|
|
885
|
+
idle(run, { timeout: 2e3 });
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
setTimeout(run, 0);
|
|
889
|
+
}
|
|
890
|
+
|
|
776
891
|
// src/platform/renderer.ts
|
|
777
892
|
var NoopPopupRenderer = class {
|
|
778
893
|
show() {
|
|
@@ -807,13 +922,20 @@ var BrowserPopupRenderer = class {
|
|
|
807
922
|
document.body.appendChild(this.container);
|
|
808
923
|
}
|
|
809
924
|
}
|
|
925
|
+
/**
|
|
926
|
+
* Descarga el chunk de `renderPopup` antes de que ningún trigger dispare, para que abrir el
|
|
927
|
+
* popup no empiece por esperar ~238 KB de JS.
|
|
928
|
+
*/
|
|
929
|
+
preload() {
|
|
930
|
+
schedulePreloadRenderPopup();
|
|
931
|
+
}
|
|
810
932
|
show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId, _renderChrome, options) {
|
|
811
933
|
if (this.visible) return;
|
|
812
934
|
if (!this.container || !document.body.contains(this.container)) this.init();
|
|
813
935
|
if (!this.container) return;
|
|
814
936
|
this.visible = true;
|
|
815
937
|
const container = this.container;
|
|
816
|
-
void import("./renderPopup-
|
|
938
|
+
void import("./renderPopup-SNDPX5RX.mjs").then(({ renderPopup }) => {
|
|
817
939
|
renderPopup(container, surveyId, productId, actions, emit, onClose, env, userId, style, sessionId, miniService, analyticsFeedbackSessionId, options);
|
|
818
940
|
});
|
|
819
941
|
}
|
|
@@ -821,6 +943,8 @@ var BrowserPopupRenderer = class {
|
|
|
821
943
|
this.visible = false;
|
|
822
944
|
if (this.container) {
|
|
823
945
|
this.container.style.display = "none";
|
|
946
|
+
this.container.style.visibility = "";
|
|
947
|
+
this.container.style.pointerEvents = "";
|
|
824
948
|
this.container.innerHTML = "";
|
|
825
949
|
}
|
|
826
950
|
}
|
|
@@ -1890,6 +2014,7 @@ var DeepdotsPopups = class {
|
|
|
1890
2014
|
this.popupDefinitions = this.validatePopupDefinitions(defs);
|
|
1891
2015
|
this.popupsLoaded = true;
|
|
1892
2016
|
this.log("Popups loaded from API", this.popupDefinitions);
|
|
2017
|
+
if (this.popupDefinitions.length) this.renderer.preload?.();
|
|
1893
2018
|
this.configureTriggersFromDefinitions();
|
|
1894
2019
|
this.processDeferredExitQueue();
|
|
1895
2020
|
if (this.pendingAutoLaunch) {
|
|
@@ -2377,7 +2502,7 @@ var DeepdotsPopups = class {
|
|
|
2377
2502
|
processDeferredExitQueue() {
|
|
2378
2503
|
const queue = this.getDeferredExitQueue();
|
|
2379
2504
|
if (!queue.length) return;
|
|
2380
|
-
const
|
|
2505
|
+
const pending2 = [];
|
|
2381
2506
|
const now = Date.now();
|
|
2382
2507
|
queue.forEach((item) => {
|
|
2383
2508
|
const def = this.popupDefinitions.find((popup) => popup.id === item.id && popup.surveyId === item.surveyId);
|
|
@@ -2388,10 +2513,10 @@ var DeepdotsPopups = class {
|
|
|
2388
2513
|
this.tryShowDeferredExitPopup(item);
|
|
2389
2514
|
return;
|
|
2390
2515
|
}
|
|
2391
|
-
|
|
2516
|
+
pending2.push(item);
|
|
2392
2517
|
this.scheduleDeferredExitPopup(item);
|
|
2393
2518
|
});
|
|
2394
|
-
this.setDeferredExitQueue(
|
|
2519
|
+
this.setDeferredExitQueue(pending2);
|
|
2395
2520
|
}
|
|
2396
2521
|
scheduleDeferredExitPopup(item) {
|
|
2397
2522
|
if (typeof window === "undefined") return;
|
|
@@ -2464,7 +2589,7 @@ var DeepdotsPopups = class {
|
|
|
2464
2589
|
async fetchPopupsFromServer() {
|
|
2465
2590
|
const apiKey = this.config?.apiKey;
|
|
2466
2591
|
const baseUrl = this.baseUrl;
|
|
2467
|
-
const userId = this.config?.userId;
|
|
2592
|
+
const userId = this.tracking?.getUserId() ?? this.config?.userId;
|
|
2468
2593
|
if (!apiKey || !baseUrl) {
|
|
2469
2594
|
this.log("Missing apiKey or baseUrl. Skipping popups fetch.");
|
|
2470
2595
|
return [];
|
|
@@ -2608,7 +2733,7 @@ var DeepdotsPopups = class {
|
|
|
2608
2733
|
}
|
|
2609
2734
|
if (!this.popupContainer) return;
|
|
2610
2735
|
const container = this.popupContainer;
|
|
2611
|
-
void import("./renderPopup-
|
|
2736
|
+
void import("./renderPopup-SNDPX5RX.mjs").then(({ renderPopup }) => {
|
|
2612
2737
|
renderPopup(
|
|
2613
2738
|
container,
|
|
2614
2739
|
surveyId,
|
|
@@ -2889,16 +3014,24 @@ function DeepdotsProvider({ config, children }) {
|
|
|
2889
3014
|
}, []);
|
|
2890
3015
|
return /* @__PURE__ */ jsxs(DeepdotsContext.Provider, { value: sdk, children: [
|
|
2891
3016
|
children,
|
|
2892
|
-
survey ?
|
|
2893
|
-
WebView
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
3017
|
+
survey ? (
|
|
3018
|
+
// El Modal se abre en cuanto hay popup, y es el HTML del WebView el que se revela solo
|
|
3019
|
+
// cuando el survey está pintado (apertura diferida): con el Modal transparente, hasta ese
|
|
3020
|
+
// momento no se ve nada, ni velo ni spinner. No se difiere el Modal con `onReady` porque
|
|
3021
|
+
// React Native no monta los hijos de un Modal cerrado: el WebView no llegaría a cargar y
|
|
3022
|
+
// el aviso no llegaría nunca. El host que quiera diferir su contenedor debe montar el
|
|
3023
|
+
// WebView invisible (ver el ejemplo de `ReactNativePopupRenderer`).
|
|
3024
|
+
/* @__PURE__ */ jsx(Modal, { visible: true, transparent: true, animationType: "slide", children: /* @__PURE__ */ jsx(View, { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
|
|
3025
|
+
WebView,
|
|
3026
|
+
{
|
|
3027
|
+
style: { flex: 1 },
|
|
3028
|
+
originWhitelist: ["*"],
|
|
3029
|
+
javaScriptEnabled: true,
|
|
3030
|
+
source: { html: survey.html, baseUrl: "https://sdk.deepdots.com/" },
|
|
3031
|
+
onMessage: (e) => rendererRef.current?.handleMessage(e.nativeEvent.data)
|
|
3032
|
+
}
|
|
3033
|
+
) }) })
|
|
3034
|
+
) : null
|
|
2902
3035
|
] });
|
|
2903
3036
|
}
|
|
2904
3037
|
export {
|