rampkit-expo-dev 0.0.24 → 0.0.26

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.
@@ -1,5 +1,6 @@
1
1
  export declare const injectedHardening = "\n(function(){\n try {\n var meta = document.querySelector('meta[name=\"viewport\"]');\n if (!meta) { meta = document.createElement('meta'); meta.name = 'viewport'; document.head.appendChild(meta); }\n meta.setAttribute('content','width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover');\n var style = document.createElement('style');\n style.textContent='html,body{overflow-x:hidden!important;} html,body,*{-webkit-user-select:none!important;user-select:none!important;-webkit-touch-callout:none!important;-ms-user-select:none!important;touch-action: pan-y;} *{-webkit-tap-highlight-color: rgba(0,0,0,0)!important;} ::selection{background: transparent!important;} ::-moz-selection{background: transparent!important;} a,img{-webkit-user-drag:none!important;user-drag:none!important;-webkit-touch-callout:none!important} input,textarea{caret-color:transparent!important;-webkit-user-select:none!important;user-select:none!important}';\n document.head.appendChild(style);\n var prevent=function(e){e.preventDefault&&e.preventDefault();};\n document.addEventListener('gesturestart',prevent,{passive:false});\n document.addEventListener('gesturechange',prevent,{passive:false});\n document.addEventListener('gestureend',prevent,{passive:false});\n document.addEventListener('dblclick',prevent,{passive:false});\n document.addEventListener('wheel',function(e){ if(e.ctrlKey) e.preventDefault(); },{passive:false});\n document.addEventListener('touchmove',function(e){ if(e.scale && e.scale !== 1) e.preventDefault(); },{passive:false});\n document.addEventListener('selectstart',prevent,{passive:false,capture:true});\n document.addEventListener('contextmenu',prevent,{passive:false,capture:true});\n document.addEventListener('copy',prevent,{passive:false,capture:true});\n document.addEventListener('cut',prevent,{passive:false,capture:true});\n document.addEventListener('paste',prevent,{passive:false,capture:true});\n document.addEventListener('dragstart',prevent,{passive:false,capture:true});\n // Belt-and-suspenders: aggressively clear any attempted selection\n var clearSel=function(){\n try{var sel=window.getSelection&&window.getSelection(); if(sel&&sel.removeAllRanges) sel.removeAllRanges();}catch(_){} }\n document.addEventListener('selectionchange',clearSel,{passive:true,capture:true});\n document.onselectstart=function(){ clearSel(); return false; };\n try{ document.documentElement.style.webkitUserSelect='none'; document.documentElement.style.userSelect='none'; }catch(_){ }\n try{ document.body.style.webkitUserSelect='none'; document.body.style.userSelect='none'; }catch(_){ }\n var __selTimer = setInterval(clearSel, 160);\n window.addEventListener('pagehide',function(){ try{ clearInterval(__selTimer); }catch(_){} });\n // Continuously enforce no-select on all elements and new nodes\n var enforceNoSelect = function(el){\n try{\n el.style && (el.style.webkitUserSelect='none', el.style.userSelect='none', el.style.webkitTouchCallout='none');\n el.setAttribute && (el.setAttribute('unselectable','on'), el.setAttribute('contenteditable','false'));\n }catch(_){}\n }\n try{\n var all=document.getElementsByTagName('*');\n for(var i=0;i<all.length;i++){ enforceNoSelect(all[i]); }\n var obs = new MutationObserver(function(muts){\n for(var j=0;j<muts.length;j++){\n var m=muts[j];\n if(m.type==='childList'){\n m.addedNodes && m.addedNodes.forEach && m.addedNodes.forEach(function(n){ if(n && n.nodeType===1){ enforceNoSelect(n); var q=n.getElementsByTagName? n.getElementsByTagName('*'): []; for(var k=0;k<q.length;k++){ enforceNoSelect(q[k]); }}});\n } else if(m.type==='attributes'){\n enforceNoSelect(m.target);\n }\n }\n });\n obs.observe(document.documentElement,{ childList:true, subtree:true, attributes:true, attributeFilter:['contenteditable','style'] });\n }catch(_){ }\n } catch(_) {}\n})(); true;\n";
2
2
  export declare const injectedNoSelect = "\n(function(){\n try {\n if (window.__rkNoSelectApplied) return true;\n window.__rkNoSelectApplied = true;\n var style = document.getElementById('rk-no-select-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'rk-no-select-style';\n style.innerHTML = \"\n * {\n user-select: none !important;\n -webkit-user-select: none !important;\n -webkit-touch-callout: none !important;\n }\n ::selection {\n background: transparent !important;\n }\n \";\n document.head.appendChild(style);\n }\n var prevent = function(e){ if(e && e.preventDefault) e.preventDefault(); return false; };\n document.addEventListener('contextmenu', prevent, { passive: false, capture: true });\n document.addEventListener('selectstart', prevent, { passive: false, capture: true });\n } catch (_) {}\n true;\n})();\n";
3
+ export declare const injectedVarsHandler = "\n(function(){\n try {\n if (window.__rkVarsHandlerApplied) return true;\n window.__rkVarsHandlerApplied = true;\n \n // Handler function that updates variables and notifies the page\n window.__rkHandleVarsUpdate = function(vars) {\n if (!vars || typeof vars !== 'object') return;\n // Update the global variables object\n window.__rampkitVariables = vars;\n // Dispatch a custom event that the page's JS can listen to for re-rendering\n try {\n document.dispatchEvent(new CustomEvent('rampkit:vars-updated', { detail: vars }));\n } catch(e) {}\n // Also try calling a global handler if the page defined one\n try {\n if (typeof window.onRampkitVarsUpdate === 'function') {\n window.onRampkitVarsUpdate(vars);\n }\n } catch(e) {}\n };\n \n // Listen for message events from React Native\n document.addEventListener('message', function(event) {\n try {\n var data = event.data;\n if (data && data.type === 'rampkit:variables' && data.vars) {\n window.__rkHandleVarsUpdate(data.vars);\n }\n } catch(e) {}\n }, false);\n \n // Also listen on window for compatibility\n window.addEventListener('message', function(event) {\n try {\n var data = event.data;\n if (data && data.type === 'rampkit:variables' && data.vars) {\n window.__rkHandleVarsUpdate(data.vars);\n }\n } catch(e) {}\n }, false);\n } catch (_) {}\n true;\n})();\n";
3
4
  export type ScreenPayload = {
4
5
  id: string;
5
6
  html: string;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.injectedNoSelect = exports.injectedHardening = void 0;
39
+ exports.injectedVarsHandler = exports.injectedNoSelect = exports.injectedHardening = void 0;
40
40
  exports.showRampkitOverlay = showRampkitOverlay;
41
41
  exports.hideRampkitOverlay = hideRampkitOverlay;
42
42
  exports.closeRampkitOverlay = closeRampkitOverlay;
@@ -125,6 +125,54 @@ exports.injectedNoSelect = `
125
125
  true;
126
126
  })();
127
127
  `;
128
+ // Robust variable handler that ensures variables are always received and applied
129
+ // This runs after content loads and sets up listeners for incoming variable updates
130
+ exports.injectedVarsHandler = `
131
+ (function(){
132
+ try {
133
+ if (window.__rkVarsHandlerApplied) return true;
134
+ window.__rkVarsHandlerApplied = true;
135
+
136
+ // Handler function that updates variables and notifies the page
137
+ window.__rkHandleVarsUpdate = function(vars) {
138
+ if (!vars || typeof vars !== 'object') return;
139
+ // Update the global variables object
140
+ window.__rampkitVariables = vars;
141
+ // Dispatch a custom event that the page's JS can listen to for re-rendering
142
+ try {
143
+ document.dispatchEvent(new CustomEvent('rampkit:vars-updated', { detail: vars }));
144
+ } catch(e) {}
145
+ // Also try calling a global handler if the page defined one
146
+ try {
147
+ if (typeof window.onRampkitVarsUpdate === 'function') {
148
+ window.onRampkitVarsUpdate(vars);
149
+ }
150
+ } catch(e) {}
151
+ };
152
+
153
+ // Listen for message events from React Native
154
+ document.addEventListener('message', function(event) {
155
+ try {
156
+ var data = event.data;
157
+ if (data && data.type === 'rampkit:variables' && data.vars) {
158
+ window.__rkHandleVarsUpdate(data.vars);
159
+ }
160
+ } catch(e) {}
161
+ }, false);
162
+
163
+ // Also listen on window for compatibility
164
+ window.addEventListener('message', function(event) {
165
+ try {
166
+ var data = event.data;
167
+ if (data && data.type === 'rampkit:variables' && data.vars) {
168
+ window.__rkHandleVarsUpdate(data.vars);
169
+ }
170
+ } catch(e) {}
171
+ }, false);
172
+ } catch (_) {}
173
+ true;
174
+ })();
175
+ `;
128
176
  function performRampkitHaptic(event) {
129
177
  if (!event || event.action !== "haptic") {
130
178
  // Backwards compatible default
@@ -225,7 +273,7 @@ function preloadRampkitOverlay(opts) {
225
273
  opacity: 0,
226
274
  top: -1000,
227
275
  left: -1000,
228
- }, children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { originWhitelist: ["*"], source: { html: docs[0] || "<html></html>" }, injectedJavaScriptBeforeContentLoaded: exports.injectedHardening, injectedJavaScript: exports.injectedNoSelect, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, hideKeyboardAccessoryView: true }) }));
276
+ }, children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { originWhitelist: ["*"], source: { html: docs[0] || "<html></html>" }, injectedJavaScriptBeforeContentLoaded: exports.injectedHardening, injectedJavaScript: exports.injectedNoSelect + exports.injectedVarsHandler, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, hideKeyboardAccessoryView: true }) }));
229
277
  preloadSibling = new react_native_root_siblings_1.default((0, jsx_runtime_1.jsx)(HiddenPreloader, {}));
230
278
  }
231
279
  catch (e) {
@@ -366,6 +414,11 @@ function Overlay(props) {
366
414
  else if (typeof pager.setPageWithoutAnimation === "function") {
367
415
  pager.setPageWithoutAnimation(nextIndex);
368
416
  }
417
+ // Explicitly send vars to the new page after setting it
418
+ // This ensures the webview receives the latest state
419
+ requestAnimationFrame(() => {
420
+ sendVarsToWebView(nextIndex);
421
+ });
369
422
  return;
370
423
  }
371
424
  setIsTransitioning(true);
@@ -380,6 +433,10 @@ function Overlay(props) {
380
433
  // @ts-ignore: method exists on PagerView instance
381
434
  (_c = (_b = (_a = pagerRef.current) === null || _a === void 0 ? void 0 : _a.setPageWithoutAnimation) === null || _b === void 0 ? void 0 : _b.call(_a, nextIndex)) !== null && _c !== void 0 ? _c : (_d = pagerRef.current) === null || _d === void 0 ? void 0 : _d.setPage(nextIndex);
382
435
  requestAnimationFrame(() => {
436
+ // Explicitly send vars to the new page after the page switch completes
437
+ // This ensures the webview receives the latest state even if onPageSelected
438
+ // timing was off during the transition
439
+ sendVarsToWebView(nextIndex);
383
440
  react_native_1.Animated.timing(fadeOpacity, {
384
441
  toValue: 0,
385
442
  duration: 160,
@@ -476,7 +533,20 @@ function Overlay(props) {
476
533
  // ensure current page is synced with latest vars when selected
477
534
  if (__DEV__)
478
535
  console.log("[Rampkit] onPageSelected", pos);
479
- sendVarsToWebView(pos);
536
+ // Send vars multiple times with increasing delays to ensure the webview
537
+ // receives them. The first send might fail if the webview isn't fully ready,
538
+ // so we retry a few times.
539
+ requestAnimationFrame(() => {
540
+ sendVarsToWebView(pos);
541
+ });
542
+ // Retry after a short delay in case the first send didn't work
543
+ setTimeout(() => {
544
+ sendVarsToWebView(pos);
545
+ }, 50);
546
+ // Final retry to catch any edge cases
547
+ setTimeout(() => {
548
+ sendVarsToWebView(pos);
549
+ }, 150);
480
550
  // Track screen change event
481
551
  if (props.onScreenChange && props.screens[pos]) {
482
552
  props.onScreenChange(pos, props.screens[pos].id);
@@ -557,7 +627,7 @@ function Overlay(props) {
557
627
  styles.root,
558
628
  !visible && styles.invisible,
559
629
  visible && { opacity: overlayOpacity },
560
- ], pointerEvents: visible && !isClosing ? "auto" : "none", children: [(0, jsx_runtime_1.jsx)(react_native_pager_view_1.default, { ref: pagerRef, style: react_native_1.StyleSheet.absoluteFill, scrollEnabled: false, initialPage: 0, onPageSelected: onPageSelected, offscreenPageLimit: props.screens.length, overScrollMode: "never", children: docs.map((doc, i) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.page, renderToHardwareTextureAndroid: true, children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { ref: (r) => (webviewsRef.current[i] = r), style: styles.webview, originWhitelist: ["*"], source: { html: doc }, injectedJavaScriptBeforeContentLoaded: exports.injectedHardening, injectedJavaScript: exports.injectedNoSelect, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, overScrollMode: "never", scalesPageToFit: false, showsHorizontalScrollIndicator: false, dataDetectorTypes: "none", allowsLinkPreview: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, javaScriptEnabled: true, domStorageEnabled: true, hideKeyboardAccessoryView: true, onLoadEnd: () => {
630
+ ], pointerEvents: visible && !isClosing ? "auto" : "none", children: [(0, jsx_runtime_1.jsx)(react_native_pager_view_1.default, { ref: pagerRef, style: react_native_1.StyleSheet.absoluteFill, scrollEnabled: false, initialPage: 0, onPageSelected: onPageSelected, offscreenPageLimit: props.screens.length, overScrollMode: "never", children: docs.map((doc, i) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.page, renderToHardwareTextureAndroid: true, children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { ref: (r) => (webviewsRef.current[i] = r), style: styles.webview, originWhitelist: ["*"], source: { html: doc }, injectedJavaScriptBeforeContentLoaded: exports.injectedHardening, injectedJavaScript: exports.injectedNoSelect + exports.injectedVarsHandler, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, overScrollMode: "never", scalesPageToFit: false, showsHorizontalScrollIndicator: false, dataDetectorTypes: "none", allowsLinkPreview: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, javaScriptEnabled: true, domStorageEnabled: true, hideKeyboardAccessoryView: true, onLoadEnd: () => {
561
631
  setLoadedCount((c) => c + 1);
562
632
  if (i === 0) {
563
633
  setFirstPageLoaded(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",