@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.
@@ -286,6 +286,11 @@ interface PopupRenderOptions {
286
286
  interface PopupRenderer {
287
287
  /** Preparar recursos si aplica */
288
288
  init?(): void;
289
+ /**
290
+ * Traer por adelantado lo que la apertura necesitará, en idle. Opcional: solo lo implementan
291
+ * los renderers cuyo coste de apertura se paga delante del usuario.
292
+ */
293
+ preload?(): void;
289
294
  /** Mostrar popup */
290
295
  show(surveyId: string, productId: string, actions: PopupActions | undefined, emit: (type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>) => void, onClose: () => void, env?: string, userId?: string, style?: PopupStyle, sessionId?: string, miniService?: string, analyticsFeedbackSessionId?: string, renderChrome?: boolean, options?: PopupRenderOptions): void;
291
296
  /** Ocultar popup */
@@ -652,23 +657,47 @@ interface ReactNativeRendererOptions {
652
657
  onShow?: (payload: ReactNativeSurveyPayload) => void;
653
658
  /** Se llama al cerrar el popup: desmonta el WebView. */
654
659
  onHide?: () => void;
660
+ /**
661
+ * Se llama cuando el survey ya está pintado dentro del WebView, o pasado el techo de espera.
662
+ *
663
+ * Sirve para no enseñar un WebView en blanco: monta el WebView en cuanto llegue `onShow` (fuera
664
+ * de pantalla o transparente) y ábrelo al recibir `onReady`. El HTML se revela solo de todas
665
+ * formas, así que el host que no lo use sigue funcionando igual.
666
+ */
667
+ onReady?: (payload: {
668
+ surveyId: string;
669
+ }) => void;
655
670
  }
656
671
  /**
657
672
  * Renderer de React Native: el SDK no puede pintar componentes RN, así que entrega el
658
673
  * HTML del survey al host (que lo monta en `react-native-webview`) y traduce los
659
674
  * mensajes del WebView a eventos de popup del SDK (→ `POST /sdk/popups`, Messaging #18–22).
660
675
  *
661
- * Uso:
676
+ * Uso: monta el WebView con `onShow` y enséñalo con `onReady`, para que el usuario no vea el
677
+ * WebView arrancando en blanco (motor + bundle del CDN + fetch del survey).
662
678
  * ```tsx
663
679
  * const renderer = new ReactNativePopupRenderer({
664
- * onShow: (p) => setSurvey({ ...p, visible: true }),
665
- * onHide: () => setSurvey((s) => ({ ...s, visible: false })),
680
+ * onShow: (p) => setSurvey({ ...p, ready: false }),
681
+ * onReady: () => setSurvey((s) => (s ? { ...s, ready: true } : s)),
682
+ * onHide: () => setSurvey(null),
666
683
  * });
667
684
  * sdk.setRenderer(renderer);
668
685
  * // …
669
- * <WebView source={{ html: survey.html }}
670
- * onMessage={(e) => renderer.handleMessage(e.nativeEvent.data)} />
686
+ * // ⚠️ Con `<Modal visible={survey.ready}>` esto NO funciona: React Native no monta los hijos
687
+ * // de un Modal cerrado, así que el WebView no empezaría a cargar y `ready` no llegaría nunca.
688
+ * // El WebView tiene que estar montado y solo invisible.
689
+ * {survey ? (
690
+ * <View style={[StyleSheet.absoluteFill, { opacity: survey.ready ? 1 : 0 }]}
691
+ * pointerEvents={survey.ready ? 'auto' : 'none'}>
692
+ * <WebView source={{ html: survey.html }}
693
+ * onMessage={(e) => renderer.handleMessage(e.nativeEvent.data)} />
694
+ * </View>
695
+ * ) : null}
671
696
  * ```
697
+ *
698
+ * Quien prefiera no complicarse puede ignorar `onReady` y abrir su Modal en `onShow`: el HTML se
699
+ * revela solo igualmente, así que el usuario verá el contenedor del host unos cientos de ms antes
700
+ * que la tarjeta, pero nunca el spinner.
672
701
  */
673
702
  declare class ReactNativePopupRenderer implements PopupRenderer {
674
703
  private options;
@@ -676,10 +705,17 @@ declare class ReactNativePopupRenderer implements PopupRenderer {
676
705
  private onCloseFn;
677
706
  private currentSurveyId;
678
707
  private partialEmitted;
708
+ private readyEmitted;
709
+ private readyTimer;
679
710
  constructor(options?: ReactNativeRendererOptions);
680
711
  init(): void;
681
712
  show(surveyId: string, productId: string, actions: PopupActions | undefined, emit: EmitFn, onClose: () => void, env?: string, userId?: string, style?: PopupStyle, sessionId?: string, miniService?: string, analyticsFeedbackSessionId?: string, renderChrome?: boolean, options?: PopupRenderOptions): void;
682
713
  hide(): void;
714
+ /** Respaldo del aviso de listo por si el WebView no llega a ejecutar el HTML. */
715
+ private armReadyFallback;
716
+ private clearReadyFallback;
717
+ /** Idempotente: el WebView puede avisar a la vez que vence el respaldo. */
718
+ private emitReady;
683
719
  /**
684
720
  * El host la conecta al `onMessage` del WebView. Traduce los mensajes del survey a
685
721
  * eventos del SDK: primera interacción → `popup_clicked` (PARTIAL), completado →
@@ -286,6 +286,11 @@ interface PopupRenderOptions {
286
286
  interface PopupRenderer {
287
287
  /** Preparar recursos si aplica */
288
288
  init?(): void;
289
+ /**
290
+ * Traer por adelantado lo que la apertura necesitará, en idle. Opcional: solo lo implementan
291
+ * los renderers cuyo coste de apertura se paga delante del usuario.
292
+ */
293
+ preload?(): void;
289
294
  /** Mostrar popup */
290
295
  show(surveyId: string, productId: string, actions: PopupActions | undefined, emit: (type: DeepdotsEventType, surveyId: string, data?: Record<string, unknown>) => void, onClose: () => void, env?: string, userId?: string, style?: PopupStyle, sessionId?: string, miniService?: string, analyticsFeedbackSessionId?: string, renderChrome?: boolean, options?: PopupRenderOptions): void;
291
296
  /** Ocultar popup */
@@ -652,23 +657,47 @@ interface ReactNativeRendererOptions {
652
657
  onShow?: (payload: ReactNativeSurveyPayload) => void;
653
658
  /** Se llama al cerrar el popup: desmonta el WebView. */
654
659
  onHide?: () => void;
660
+ /**
661
+ * Se llama cuando el survey ya está pintado dentro del WebView, o pasado el techo de espera.
662
+ *
663
+ * Sirve para no enseñar un WebView en blanco: monta el WebView en cuanto llegue `onShow` (fuera
664
+ * de pantalla o transparente) y ábrelo al recibir `onReady`. El HTML se revela solo de todas
665
+ * formas, así que el host que no lo use sigue funcionando igual.
666
+ */
667
+ onReady?: (payload: {
668
+ surveyId: string;
669
+ }) => void;
655
670
  }
656
671
  /**
657
672
  * Renderer de React Native: el SDK no puede pintar componentes RN, así que entrega el
658
673
  * HTML del survey al host (que lo monta en `react-native-webview`) y traduce los
659
674
  * mensajes del WebView a eventos de popup del SDK (→ `POST /sdk/popups`, Messaging #18–22).
660
675
  *
661
- * Uso:
676
+ * Uso: monta el WebView con `onShow` y enséñalo con `onReady`, para que el usuario no vea el
677
+ * WebView arrancando en blanco (motor + bundle del CDN + fetch del survey).
662
678
  * ```tsx
663
679
  * const renderer = new ReactNativePopupRenderer({
664
- * onShow: (p) => setSurvey({ ...p, visible: true }),
665
- * onHide: () => setSurvey((s) => ({ ...s, visible: false })),
680
+ * onShow: (p) => setSurvey({ ...p, ready: false }),
681
+ * onReady: () => setSurvey((s) => (s ? { ...s, ready: true } : s)),
682
+ * onHide: () => setSurvey(null),
666
683
  * });
667
684
  * sdk.setRenderer(renderer);
668
685
  * // …
669
- * <WebView source={{ html: survey.html }}
670
- * onMessage={(e) => renderer.handleMessage(e.nativeEvent.data)} />
686
+ * // ⚠️ Con `<Modal visible={survey.ready}>` esto NO funciona: React Native no monta los hijos
687
+ * // de un Modal cerrado, así que el WebView no empezaría a cargar y `ready` no llegaría nunca.
688
+ * // El WebView tiene que estar montado y solo invisible.
689
+ * {survey ? (
690
+ * <View style={[StyleSheet.absoluteFill, { opacity: survey.ready ? 1 : 0 }]}
691
+ * pointerEvents={survey.ready ? 'auto' : 'none'}>
692
+ * <WebView source={{ html: survey.html }}
693
+ * onMessage={(e) => renderer.handleMessage(e.nativeEvent.data)} />
694
+ * </View>
695
+ * ) : null}
671
696
  * ```
697
+ *
698
+ * Quien prefiera no complicarse puede ignorar `onReady` y abrir su Modal en `onShow`: el HTML se
699
+ * revela solo igualmente, así que el usuario verá el contenedor del host unos cientos de ms antes
700
+ * que la tarjeta, pero nunca el spinner.
672
701
  */
673
702
  declare class ReactNativePopupRenderer implements PopupRenderer {
674
703
  private options;
@@ -676,10 +705,17 @@ declare class ReactNativePopupRenderer implements PopupRenderer {
676
705
  private onCloseFn;
677
706
  private currentSurveyId;
678
707
  private partialEmitted;
708
+ private readyEmitted;
709
+ private readyTimer;
679
710
  constructor(options?: ReactNativeRendererOptions);
680
711
  init(): void;
681
712
  show(surveyId: string, productId: string, actions: PopupActions | undefined, emit: EmitFn, onClose: () => void, env?: string, userId?: string, style?: PopupStyle, sessionId?: string, miniService?: string, analyticsFeedbackSessionId?: string, renderChrome?: boolean, options?: PopupRenderOptions): void;
682
713
  hide(): void;
714
+ /** Respaldo del aviso de listo por si el WebView no llega a ejecutar el HTML. */
715
+ private armReadyFallback;
716
+ private clearReadyFallback;
717
+ /** Idempotente: el WebView puede avisar a la vez que vence el respaldo. */
718
+ private emitReady;
683
719
  /**
684
720
  * El host la conecta al `onMessage` del WebView. Traduce los mensajes del survey a
685
721
  * eventos del SDK: primera interacción → `popup_clicked` (PARTIAL), completado →