rampkit-expo-dev 0.0.39 → 0.0.41
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/build/RampkitOverlay.d.ts +1 -0
- package/build/RampkitOverlay.js +409 -298
- package/package.json +1 -1
|
@@ -2,6 +2,7 @@ import { RampKitContext } from "./types";
|
|
|
2
2
|
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";
|
|
3
3
|
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";
|
|
4
4
|
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";
|
|
5
|
+
export declare const injectedButtonAnimations = "\n(function(){\n try {\n if (window.__rkButtonAnimApplied) return true;\n window.__rkButtonAnimApplied = true;\n \n // Add styles for button animations\n var style = document.createElement('style');\n style.id = 'rk-button-anim-style';\n style.innerHTML = `\n /* Base transition for all interactive elements */\n [data-rampkit-action],\n [data-rampkit-navigate],\n [data-rampkit-tap],\n [onclick],\n button,\n a[href],\n .rk-interactive,\n .rk-button {\n transform: scale(1);\n opacity: 1;\n will-change: transform, opacity;\n }\n \n /* Pressed state - applied via JS */\n .rk-pressed {\n transform: scale(0.97) !important;\n opacity: 0.8 !important;\n transition: transform 80ms cubic-bezier(0.25, 0.1, 0.25, 1), \n opacity 80ms cubic-bezier(0.25, 0.1, 0.25, 1) !important;\n }\n \n /* Released state - spring-like bounce back */\n .rk-released {\n transform: scale(1) !important;\n opacity: 1 !important;\n transition: transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1), \n opacity 280ms cubic-bezier(0.34, 1.56, 0.64, 1) !important;\n }\n `;\n document.head.appendChild(style);\n \n // Check if element is interactive\n function isInteractive(el) {\n if (!el || !el.tagName) return false;\n var tag = el.tagName.toLowerCase();\n if (tag === 'button' || tag === 'a') return true;\n if (el.hasAttribute('data-rampkit-action')) return true;\n if (el.hasAttribute('data-rampkit-navigate')) return true;\n if (el.hasAttribute('data-rampkit-tap')) return true;\n if (el.hasAttribute('onclick')) return true;\n if (el.classList.contains('rk-interactive')) return true;\n if (el.classList.contains('rk-button')) return true;\n return false;\n }\n \n // Find the interactive parent element\n function findInteractiveElement(el) {\n var current = el;\n var maxDepth = 10; // Prevent infinite loops\n while (current && maxDepth > 0) {\n if (isInteractive(current)) return current;\n current = current.parentElement;\n maxDepth--;\n }\n return null;\n }\n \n // Track currently pressed element\n var pressedElement = null;\n var pressTimeout = null;\n \n // Handle touch start - immediate press animation\n function handleTouchStart(e) {\n try {\n var target = findInteractiveElement(e.target);\n if (!target) return;\n \n // Clear any pending release animation\n if (pressTimeout) {\n clearTimeout(pressTimeout);\n pressTimeout = null;\n }\n \n // Remove released class and add pressed class\n target.classList.remove('rk-released');\n target.classList.add('rk-pressed');\n pressedElement = target;\n } catch(_) {}\n }\n \n // Handle touch end - spring release animation\n function handleTouchEnd(e) {\n try {\n if (!pressedElement) return;\n var target = pressedElement;\n \n // Switch from pressed to released for spring animation\n target.classList.remove('rk-pressed');\n target.classList.add('rk-released');\n \n // Clean up after animation completes\n pressTimeout = setTimeout(function() {\n target.classList.remove('rk-released');\n pressTimeout = null;\n }, 300);\n \n pressedElement = null;\n } catch(_) {}\n }\n \n // Handle touch cancel - reset without animation\n function handleTouchCancel(e) {\n try {\n if (!pressedElement) return;\n pressedElement.classList.remove('rk-pressed');\n pressedElement.classList.remove('rk-released');\n pressedElement = null;\n if (pressTimeout) {\n clearTimeout(pressTimeout);\n pressTimeout = null;\n }\n } catch(_) {}\n }\n \n // Use capture phase to get events before they're handled\n document.addEventListener('touchstart', handleTouchStart, { passive: true, capture: true });\n document.addEventListener('touchend', handleTouchEnd, { passive: true, capture: true });\n document.addEventListener('touchcancel', handleTouchCancel, { passive: true, capture: true });\n \n // Also handle mouse events for web testing\n document.addEventListener('mousedown', handleTouchStart, { passive: true, capture: true });\n document.addEventListener('mouseup', handleTouchEnd, { passive: true, capture: true });\n document.addEventListener('mouseleave', handleTouchCancel, { passive: true, capture: true });\n \n } catch (_) {}\n true;\n})();\n";
|
|
5
6
|
export type ScreenPayload = {
|
|
6
7
|
id: string;
|
|
7
8
|
html: string;
|
package/build/RampkitOverlay.js
CHANGED
|
@@ -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.injectedVarsHandler = exports.injectedNoSelect = exports.injectedHardening = void 0;
|
|
39
|
+
exports.injectedButtonAnimations = exports.injectedVarsHandler = exports.injectedNoSelect = exports.injectedHardening = void 0;
|
|
40
40
|
exports.showRampkitOverlay = showRampkitOverlay;
|
|
41
41
|
exports.hideRampkitOverlay = hideRampkitOverlay;
|
|
42
42
|
exports.closeRampkitOverlay = closeRampkitOverlay;
|
|
@@ -173,6 +173,147 @@ exports.injectedVarsHandler = `
|
|
|
173
173
|
true;
|
|
174
174
|
})();
|
|
175
175
|
`;
|
|
176
|
+
// Button tap animation script - handles spring animations for interactive elements
|
|
177
|
+
// Triggers on touchstart (not click) for immediate feedback
|
|
178
|
+
exports.injectedButtonAnimations = `
|
|
179
|
+
(function(){
|
|
180
|
+
try {
|
|
181
|
+
if (window.__rkButtonAnimApplied) return true;
|
|
182
|
+
window.__rkButtonAnimApplied = true;
|
|
183
|
+
|
|
184
|
+
// Add styles for button animations
|
|
185
|
+
var style = document.createElement('style');
|
|
186
|
+
style.id = 'rk-button-anim-style';
|
|
187
|
+
style.innerHTML = \`
|
|
188
|
+
/* Base transition for all interactive elements */
|
|
189
|
+
[data-rampkit-action],
|
|
190
|
+
[data-rampkit-navigate],
|
|
191
|
+
[data-rampkit-tap],
|
|
192
|
+
[onclick],
|
|
193
|
+
button,
|
|
194
|
+
a[href],
|
|
195
|
+
.rk-interactive,
|
|
196
|
+
.rk-button {
|
|
197
|
+
transform: scale(1);
|
|
198
|
+
opacity: 1;
|
|
199
|
+
will-change: transform, opacity;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* Pressed state - applied via JS */
|
|
203
|
+
.rk-pressed {
|
|
204
|
+
transform: scale(0.97) !important;
|
|
205
|
+
opacity: 0.8 !important;
|
|
206
|
+
transition: transform 80ms cubic-bezier(0.25, 0.1, 0.25, 1),
|
|
207
|
+
opacity 80ms cubic-bezier(0.25, 0.1, 0.25, 1) !important;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* Released state - spring-like bounce back */
|
|
211
|
+
.rk-released {
|
|
212
|
+
transform: scale(1) !important;
|
|
213
|
+
opacity: 1 !important;
|
|
214
|
+
transition: transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
215
|
+
opacity 280ms cubic-bezier(0.34, 1.56, 0.64, 1) !important;
|
|
216
|
+
}
|
|
217
|
+
\`;
|
|
218
|
+
document.head.appendChild(style);
|
|
219
|
+
|
|
220
|
+
// Check if element is interactive
|
|
221
|
+
function isInteractive(el) {
|
|
222
|
+
if (!el || !el.tagName) return false;
|
|
223
|
+
var tag = el.tagName.toLowerCase();
|
|
224
|
+
if (tag === 'button' || tag === 'a') return true;
|
|
225
|
+
if (el.hasAttribute('data-rampkit-action')) return true;
|
|
226
|
+
if (el.hasAttribute('data-rampkit-navigate')) return true;
|
|
227
|
+
if (el.hasAttribute('data-rampkit-tap')) return true;
|
|
228
|
+
if (el.hasAttribute('onclick')) return true;
|
|
229
|
+
if (el.classList.contains('rk-interactive')) return true;
|
|
230
|
+
if (el.classList.contains('rk-button')) return true;
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Find the interactive parent element
|
|
235
|
+
function findInteractiveElement(el) {
|
|
236
|
+
var current = el;
|
|
237
|
+
var maxDepth = 10; // Prevent infinite loops
|
|
238
|
+
while (current && maxDepth > 0) {
|
|
239
|
+
if (isInteractive(current)) return current;
|
|
240
|
+
current = current.parentElement;
|
|
241
|
+
maxDepth--;
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Track currently pressed element
|
|
247
|
+
var pressedElement = null;
|
|
248
|
+
var pressTimeout = null;
|
|
249
|
+
|
|
250
|
+
// Handle touch start - immediate press animation
|
|
251
|
+
function handleTouchStart(e) {
|
|
252
|
+
try {
|
|
253
|
+
var target = findInteractiveElement(e.target);
|
|
254
|
+
if (!target) return;
|
|
255
|
+
|
|
256
|
+
// Clear any pending release animation
|
|
257
|
+
if (pressTimeout) {
|
|
258
|
+
clearTimeout(pressTimeout);
|
|
259
|
+
pressTimeout = null;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Remove released class and add pressed class
|
|
263
|
+
target.classList.remove('rk-released');
|
|
264
|
+
target.classList.add('rk-pressed');
|
|
265
|
+
pressedElement = target;
|
|
266
|
+
} catch(_) {}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Handle touch end - spring release animation
|
|
270
|
+
function handleTouchEnd(e) {
|
|
271
|
+
try {
|
|
272
|
+
if (!pressedElement) return;
|
|
273
|
+
var target = pressedElement;
|
|
274
|
+
|
|
275
|
+
// Switch from pressed to released for spring animation
|
|
276
|
+
target.classList.remove('rk-pressed');
|
|
277
|
+
target.classList.add('rk-released');
|
|
278
|
+
|
|
279
|
+
// Clean up after animation completes
|
|
280
|
+
pressTimeout = setTimeout(function() {
|
|
281
|
+
target.classList.remove('rk-released');
|
|
282
|
+
pressTimeout = null;
|
|
283
|
+
}, 300);
|
|
284
|
+
|
|
285
|
+
pressedElement = null;
|
|
286
|
+
} catch(_) {}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Handle touch cancel - reset without animation
|
|
290
|
+
function handleTouchCancel(e) {
|
|
291
|
+
try {
|
|
292
|
+
if (!pressedElement) return;
|
|
293
|
+
pressedElement.classList.remove('rk-pressed');
|
|
294
|
+
pressedElement.classList.remove('rk-released');
|
|
295
|
+
pressedElement = null;
|
|
296
|
+
if (pressTimeout) {
|
|
297
|
+
clearTimeout(pressTimeout);
|
|
298
|
+
pressTimeout = null;
|
|
299
|
+
}
|
|
300
|
+
} catch(_) {}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Use capture phase to get events before they're handled
|
|
304
|
+
document.addEventListener('touchstart', handleTouchStart, { passive: true, capture: true });
|
|
305
|
+
document.addEventListener('touchend', handleTouchEnd, { passive: true, capture: true });
|
|
306
|
+
document.addEventListener('touchcancel', handleTouchCancel, { passive: true, capture: true });
|
|
307
|
+
|
|
308
|
+
// Also handle mouse events for web testing
|
|
309
|
+
document.addEventListener('mousedown', handleTouchStart, { passive: true, capture: true });
|
|
310
|
+
document.addEventListener('mouseup', handleTouchEnd, { passive: true, capture: true });
|
|
311
|
+
document.addEventListener('mouseleave', handleTouchCancel, { passive: true, capture: true });
|
|
312
|
+
|
|
313
|
+
} catch (_) {}
|
|
314
|
+
true;
|
|
315
|
+
})();
|
|
316
|
+
`;
|
|
176
317
|
function performRampkitHaptic(event) {
|
|
177
318
|
if (!event || event.action !== "haptic") {
|
|
178
319
|
// Backwards compatible default
|
|
@@ -272,7 +413,7 @@ function preloadRampkitOverlay(opts) {
|
|
|
272
413
|
opacity: 0,
|
|
273
414
|
top: -1000,
|
|
274
415
|
left: -1000,
|
|
275
|
-
}, 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 }) }));
|
|
416
|
+
}, 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 + exports.injectedButtonAnimations, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", bounces: false, scrollEnabled: false, allowsInlineMediaPlayback: true, mediaPlaybackRequiresUserAction: false, cacheEnabled: true, hideKeyboardAccessoryView: true }) }));
|
|
276
417
|
preloadSibling = new react_native_root_siblings_1.default((0, jsx_runtime_1.jsx)(HiddenPreloader, {}));
|
|
277
418
|
}
|
|
278
419
|
catch (e) {
|
|
@@ -432,14 +573,9 @@ function Overlay(props) {
|
|
|
432
573
|
const [onboardingCompleted, setOnboardingCompleted] = (0, react_1.useState)(false);
|
|
433
574
|
const overlayOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
434
575
|
const fadeOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
435
|
-
// slideFade animation values
|
|
436
|
-
const
|
|
437
|
-
const
|
|
438
|
-
const slideFadeIncomingOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
439
|
-
const slideFadeIncomingTranslateX = (0, react_1.useRef)(new react_native_1.Animated.Value(SLIDE_FADE_OFFSET)).current;
|
|
440
|
-
const [slideFadeActive, setSlideFadeActive] = (0, react_1.useState)(false);
|
|
441
|
-
const [slideFadeOutgoingIndex, setSlideFadeOutgoingIndex] = (0, react_1.useState)(null);
|
|
442
|
-
const [slideFadeIncomingIndex, setSlideFadeIncomingIndex] = (0, react_1.useState)(null);
|
|
576
|
+
// slideFade animation values - animates the PagerView container
|
|
577
|
+
const pagerOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
|
|
578
|
+
const pagerTranslateX = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
|
|
443
579
|
const allLoaded = loadedCount >= props.screens.length;
|
|
444
580
|
const hasTrackedInitialScreen = (0, react_1.useRef)(false);
|
|
445
581
|
// shared vars across all webviews
|
|
@@ -521,68 +657,55 @@ function Overlay(props) {
|
|
|
521
657
|
});
|
|
522
658
|
return;
|
|
523
659
|
}
|
|
524
|
-
// slideFade animation:
|
|
525
|
-
//
|
|
660
|
+
// slideFade animation: smooth slide + fade transition
|
|
661
|
+
// Animates the PagerView container out, switches page, then animates back in
|
|
526
662
|
if (animationType === "slidefade") {
|
|
527
663
|
setIsTransitioning(true);
|
|
528
664
|
// Determine direction: forward (nextIndex > index) or backward
|
|
529
665
|
const isForward = nextIndex > index;
|
|
530
666
|
const direction = isForward ? 1 : -1;
|
|
531
|
-
|
|
532
|
-
setSlideFadeOutgoingIndex(index);
|
|
533
|
-
setSlideFadeIncomingIndex(nextIndex);
|
|
534
|
-
// Set initial positions for the animation
|
|
535
|
-
// Outgoing: starts visible at position 0
|
|
536
|
-
slideFadeOutgoingOpacity.setValue(1);
|
|
537
|
-
slideFadeOutgoingTranslateX.setValue(0);
|
|
538
|
-
// Incoming: starts invisible, offset in the direction we're navigating
|
|
539
|
-
slideFadeIncomingOpacity.setValue(0);
|
|
540
|
-
slideFadeIncomingTranslateX.setValue(SLIDE_FADE_OFFSET * direction);
|
|
541
|
-
// Activate the slideFade overlay
|
|
542
|
-
setSlideFadeActive(true);
|
|
543
|
-
// Switch the underlying PagerView immediately (without animation)
|
|
544
|
-
// so when the overlay fades away, the correct page is underneath
|
|
545
|
-
requestAnimationFrame(() => {
|
|
546
|
-
var _a, _b, _c, _d;
|
|
547
|
-
// @ts-ignore: method exists on PagerView instance
|
|
548
|
-
(_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);
|
|
549
|
-
});
|
|
550
|
-
// Run all 4 animations simultaneously
|
|
667
|
+
const halfDuration = SLIDE_FADE_DURATION / 2;
|
|
551
668
|
const timingConfig = {
|
|
552
|
-
duration:
|
|
669
|
+
duration: halfDuration,
|
|
553
670
|
easing: react_native_1.Easing.out(react_native_1.Easing.ease),
|
|
554
671
|
useNativeDriver: true,
|
|
555
672
|
};
|
|
673
|
+
// Phase 1: Fade out and slide the current page in exit direction
|
|
556
674
|
react_native_1.Animated.parallel([
|
|
557
|
-
|
|
558
|
-
react_native_1.Animated.timing(slideFadeOutgoingOpacity, {
|
|
675
|
+
react_native_1.Animated.timing(pagerOpacity, {
|
|
559
676
|
toValue: 0,
|
|
560
677
|
...timingConfig,
|
|
561
678
|
}),
|
|
562
|
-
react_native_1.Animated.timing(
|
|
563
|
-
toValue: -SLIDE_FADE_OFFSET * direction,
|
|
564
|
-
...timingConfig,
|
|
565
|
-
}),
|
|
566
|
-
// Incoming: fade in and slide to center
|
|
567
|
-
react_native_1.Animated.timing(slideFadeIncomingOpacity, {
|
|
568
|
-
toValue: 1,
|
|
569
|
-
...timingConfig,
|
|
570
|
-
}),
|
|
571
|
-
react_native_1.Animated.timing(slideFadeIncomingTranslateX, {
|
|
572
|
-
toValue: 0,
|
|
679
|
+
react_native_1.Animated.timing(pagerTranslateX, {
|
|
680
|
+
toValue: -SLIDE_FADE_OFFSET * direction * 0.5, // Slide out in opposite direction
|
|
573
681
|
...timingConfig,
|
|
574
682
|
}),
|
|
575
683
|
]).start(() => {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
//
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
684
|
+
var _a, _b, _c, _d;
|
|
685
|
+
// Switch page instantly while invisible
|
|
686
|
+
// @ts-ignore: method exists on PagerView instance
|
|
687
|
+
(_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);
|
|
688
|
+
// Set up for incoming animation - start from the direction we're navigating from
|
|
689
|
+
pagerTranslateX.setValue(SLIDE_FADE_OFFSET * direction * 0.5);
|
|
690
|
+
// Phase 2: Fade in and slide the new page to center
|
|
691
|
+
react_native_1.Animated.parallel([
|
|
692
|
+
react_native_1.Animated.timing(pagerOpacity, {
|
|
693
|
+
toValue: 1,
|
|
694
|
+
duration: halfDuration,
|
|
695
|
+
easing: react_native_1.Easing.out(react_native_1.Easing.ease),
|
|
696
|
+
useNativeDriver: true,
|
|
697
|
+
}),
|
|
698
|
+
react_native_1.Animated.timing(pagerTranslateX, {
|
|
699
|
+
toValue: 0,
|
|
700
|
+
duration: halfDuration,
|
|
701
|
+
easing: react_native_1.Easing.out(react_native_1.Easing.ease),
|
|
702
|
+
useNativeDriver: true,
|
|
703
|
+
}),
|
|
704
|
+
]).start(() => {
|
|
705
|
+
// Send vars to the new page
|
|
706
|
+
sendVarsToWebView(nextIndex);
|
|
707
|
+
setIsTransitioning(false);
|
|
708
|
+
});
|
|
586
709
|
});
|
|
587
710
|
return;
|
|
588
711
|
}
|
|
@@ -839,138 +962,166 @@ function Overlay(props) {
|
|
|
839
962
|
styles.root,
|
|
840
963
|
!visible && styles.invisible,
|
|
841
964
|
visible && { opacity: overlayOpacity },
|
|
842
|
-
], pointerEvents: visible && !isClosing ? "auto" : "none", children: [(0, jsx_runtime_1.jsx)(
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
}, onMessage: (ev) => {
|
|
857
|
-
var _a, _b, _c, _d;
|
|
858
|
-
const raw = ev.nativeEvent.data;
|
|
859
|
-
console.log("raw", raw);
|
|
860
|
-
// Accept either raw strings or JSON payloads from your editor
|
|
861
|
-
try {
|
|
862
|
-
// JSON path
|
|
863
|
-
const data = JSON.parse(raw);
|
|
864
|
-
// 1) Variables from a page → update shared + broadcast to OTHER pages
|
|
865
|
-
// This mirrors the iOS SDK pattern with stale value filtering.
|
|
866
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:variables" &&
|
|
867
|
-
(data === null || data === void 0 ? void 0 : data.vars) &&
|
|
868
|
-
typeof data.vars === "object") {
|
|
869
|
-
if (__DEV__)
|
|
870
|
-
console.log("[Rampkit] received variables from page", i, data.vars);
|
|
871
|
-
// Check if this page is within the stale value window
|
|
872
|
-
// (we recently sent vars to it and it may be echoing back defaults)
|
|
873
|
-
const now = Date.now();
|
|
874
|
-
const lastSendTime = lastVarsSendTimeRef.current[i] || 0;
|
|
875
|
-
const timeSinceSend = now - lastSendTime;
|
|
876
|
-
const isWithinStaleWindow = timeSinceSend < STALE_VALUE_WINDOW_MS;
|
|
877
|
-
if (__DEV__) {
|
|
878
|
-
console.log("[Rampkit] stale check:", {
|
|
879
|
-
pageIndex: i,
|
|
880
|
-
isWithinStaleWindow,
|
|
881
|
-
timeSinceSend,
|
|
882
|
-
});
|
|
965
|
+
], pointerEvents: visible && !isClosing ? "auto" : "none", children: [(0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { style: [
|
|
966
|
+
react_native_1.StyleSheet.absoluteFill,
|
|
967
|
+
{
|
|
968
|
+
opacity: pagerOpacity,
|
|
969
|
+
transform: [{ translateX: pagerTranslateX }],
|
|
970
|
+
},
|
|
971
|
+
], 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 + exports.injectedButtonAnimations, 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: () => {
|
|
972
|
+
setLoadedCount((c) => c + 1);
|
|
973
|
+
if (i === 0) {
|
|
974
|
+
setFirstPageLoaded(true);
|
|
975
|
+
// Track initial screen view
|
|
976
|
+
if (!hasTrackedInitialScreen.current && props.onScreenChange && props.screens[0]) {
|
|
977
|
+
hasTrackedInitialScreen.current = true;
|
|
978
|
+
props.onScreenChange(0, props.screens[0].id);
|
|
883
979
|
}
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
980
|
+
}
|
|
981
|
+
// Initialize this page with current vars (isInitialLoad=true to enable stale filter)
|
|
982
|
+
if (__DEV__)
|
|
983
|
+
console.log("[Rampkit] onLoadEnd init send vars", i);
|
|
984
|
+
sendVarsToWebView(i, true);
|
|
985
|
+
}, onMessage: (ev) => {
|
|
986
|
+
var _a, _b, _c, _d;
|
|
987
|
+
const raw = ev.nativeEvent.data;
|
|
988
|
+
console.log("raw", raw);
|
|
989
|
+
// Accept either raw strings or JSON payloads from your editor
|
|
990
|
+
try {
|
|
991
|
+
// JSON path
|
|
992
|
+
const data = JSON.parse(raw);
|
|
993
|
+
// 1) Variables from a page → update shared + broadcast to OTHER pages
|
|
994
|
+
// This mirrors the iOS SDK pattern with stale value filtering.
|
|
995
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:variables" &&
|
|
996
|
+
(data === null || data === void 0 ? void 0 : data.vars) &&
|
|
997
|
+
typeof data.vars === "object") {
|
|
998
|
+
if (__DEV__)
|
|
999
|
+
console.log("[Rampkit] received variables from page", i, data.vars);
|
|
1000
|
+
// Check if this page is within the stale value window
|
|
1001
|
+
// (we recently sent vars to it and it may be echoing back defaults)
|
|
1002
|
+
const now = Date.now();
|
|
1003
|
+
const lastSendTime = lastVarsSendTimeRef.current[i] || 0;
|
|
1004
|
+
const timeSinceSend = now - lastSendTime;
|
|
1005
|
+
const isWithinStaleWindow = timeSinceSend < STALE_VALUE_WINDOW_MS;
|
|
1006
|
+
if (__DEV__) {
|
|
1007
|
+
console.log("[Rampkit] stale check:", {
|
|
1008
|
+
pageIndex: i,
|
|
1009
|
+
isWithinStaleWindow,
|
|
1010
|
+
timeSinceSend,
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
let changed = false;
|
|
1014
|
+
const newVars = {};
|
|
1015
|
+
for (const [key, value] of Object.entries(data.vars)) {
|
|
1016
|
+
const hasHostVal = Object.prototype.hasOwnProperty.call(varsRef.current, key);
|
|
1017
|
+
const hostVal = varsRef.current[key];
|
|
1018
|
+
// Stale value filtering (matches iOS SDK behavior):
|
|
1019
|
+
// If we're within the stale window, don't let empty/default values
|
|
1020
|
+
// overwrite existing non-empty host values.
|
|
1021
|
+
// This prevents pages from clobbering user input with cached defaults
|
|
1022
|
+
// when they first become active/visible.
|
|
1023
|
+
if (isWithinStaleWindow && hasHostVal) {
|
|
1024
|
+
const hostIsNonEmpty = hostVal !== "" && hostVal !== null && hostVal !== undefined;
|
|
1025
|
+
const incomingIsEmpty = value === "" || value === null || value === undefined;
|
|
1026
|
+
if (hostIsNonEmpty && incomingIsEmpty) {
|
|
1027
|
+
if (__DEV__) {
|
|
1028
|
+
console.log(`[Rampkit] filtering stale empty value for key "${key}": keeping "${hostVal}"`);
|
|
1029
|
+
}
|
|
1030
|
+
continue; // Skip this key, keep host value
|
|
900
1031
|
}
|
|
901
|
-
|
|
1032
|
+
}
|
|
1033
|
+
// Accept the update if value is different
|
|
1034
|
+
if (!hasHostVal || hostVal !== value) {
|
|
1035
|
+
newVars[key] = value;
|
|
1036
|
+
changed = true;
|
|
902
1037
|
}
|
|
903
1038
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1039
|
+
if (changed) {
|
|
1040
|
+
varsRef.current = { ...varsRef.current, ...newVars };
|
|
1041
|
+
// Broadcast to all WebViews EXCEPT the source (index i)
|
|
1042
|
+
// This prevents echo loops and matches iOS SDK behavior
|
|
1043
|
+
broadcastVars(i);
|
|
908
1044
|
}
|
|
1045
|
+
return;
|
|
909
1046
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1047
|
+
// 2) A page asked for current vars → send only to that page
|
|
1048
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:request-vars") {
|
|
1049
|
+
if (__DEV__)
|
|
1050
|
+
console.log("[Rampkit] request-vars from page", i);
|
|
1051
|
+
sendVarsToWebView(i);
|
|
1052
|
+
return;
|
|
915
1053
|
}
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
// 3) A page requested an in-app review prompt
|
|
926
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:request-review" ||
|
|
927
|
-
(data === null || data === void 0 ? void 0 : data.type) === "rampkit:review") {
|
|
928
|
-
(async () => {
|
|
929
|
-
try {
|
|
930
|
-
const available = await RampKitNative_1.StoreReview.isAvailableAsync();
|
|
931
|
-
if (available) {
|
|
932
|
-
await RampKitNative_1.StoreReview.requestReview();
|
|
1054
|
+
// 3) A page requested an in-app review prompt
|
|
1055
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:request-review" ||
|
|
1056
|
+
(data === null || data === void 0 ? void 0 : data.type) === "rampkit:review") {
|
|
1057
|
+
(async () => {
|
|
1058
|
+
try {
|
|
1059
|
+
const available = await RampKitNative_1.StoreReview.isAvailableAsync();
|
|
1060
|
+
if (available) {
|
|
1061
|
+
await RampKitNative_1.StoreReview.requestReview();
|
|
1062
|
+
}
|
|
933
1063
|
}
|
|
1064
|
+
catch (_) { }
|
|
1065
|
+
})();
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
// 4) A page requested notification permission
|
|
1069
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:request-notification-permission") {
|
|
1070
|
+
handleNotificationPermissionRequest({
|
|
1071
|
+
ios: data === null || data === void 0 ? void 0 : data.ios,
|
|
1072
|
+
android: data === null || data === void 0 ? void 0 : data.android,
|
|
1073
|
+
behavior: data === null || data === void 0 ? void 0 : data.behavior,
|
|
1074
|
+
});
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
// 5) Onboarding finished event from page
|
|
1078
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:onboarding-finished") {
|
|
1079
|
+
setOnboardingCompleted(true);
|
|
1080
|
+
try {
|
|
1081
|
+
(_a = props.onOnboardingFinished) === null || _a === void 0 ? void 0 : _a.call(props, data === null || data === void 0 ? void 0 : data.payload);
|
|
934
1082
|
}
|
|
935
1083
|
catch (_) { }
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
}
|
|
939
|
-
// 4) A page requested notification permission
|
|
940
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:request-notification-permission") {
|
|
941
|
-
handleNotificationPermissionRequest({
|
|
942
|
-
ios: data === null || data === void 0 ? void 0 : data.ios,
|
|
943
|
-
android: data === null || data === void 0 ? void 0 : data.android,
|
|
944
|
-
behavior: data === null || data === void 0 ? void 0 : data.behavior,
|
|
945
|
-
});
|
|
946
|
-
return;
|
|
947
|
-
}
|
|
948
|
-
// 5) Onboarding finished event from page
|
|
949
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:onboarding-finished") {
|
|
950
|
-
setOnboardingCompleted(true);
|
|
951
|
-
try {
|
|
952
|
-
(_a = props.onOnboardingFinished) === null || _a === void 0 ? void 0 : _a.call(props, data === null || data === void 0 ? void 0 : data.payload);
|
|
1084
|
+
handleRequestClose({ completed: true });
|
|
1085
|
+
return;
|
|
953
1086
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
(_b = props.onShowPaywall) === null || _b === void 0 ? void 0 : _b.call(props, data === null || data === void 0 ? void 0 : data.payload);
|
|
1087
|
+
// 6) Request to show paywall
|
|
1088
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:show-paywall") {
|
|
1089
|
+
try {
|
|
1090
|
+
(_b = props.onShowPaywall) === null || _b === void 0 ? void 0 : _b.call(props, data === null || data === void 0 ? void 0 : data.payload);
|
|
1091
|
+
}
|
|
1092
|
+
catch (_) { }
|
|
1093
|
+
return;
|
|
962
1094
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1095
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:continue" ||
|
|
1096
|
+
(data === null || data === void 0 ? void 0 : data.type) === "continue") {
|
|
1097
|
+
handleAdvance(i, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
1098
|
+
return;
|
|
1099
|
+
}
|
|
1100
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:navigate") {
|
|
1101
|
+
const target = data === null || data === void 0 ? void 0 : data.targetScreenId;
|
|
1102
|
+
if (target === "__goBack__") {
|
|
1103
|
+
if (i > 0) {
|
|
1104
|
+
navigateToIndex(i - 1, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
handleRequestClose();
|
|
1108
|
+
}
|
|
1109
|
+
return;
|
|
1110
|
+
}
|
|
1111
|
+
if (!target || target === "__continue__") {
|
|
1112
|
+
handleAdvance(i, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
const targetIndex = props.screens.findIndex((s) => s.id === target);
|
|
1116
|
+
if (targetIndex >= 0) {
|
|
1117
|
+
navigateToIndex(targetIndex, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
handleAdvance(i);
|
|
1121
|
+
}
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:goBack") {
|
|
974
1125
|
if (i > 0) {
|
|
975
1126
|
navigateToIndex(i - 1, (data === null || data === void 0 ? void 0 : data.animation) || "fade");
|
|
976
1127
|
}
|
|
@@ -979,89 +1130,56 @@ function Overlay(props) {
|
|
|
979
1130
|
}
|
|
980
1131
|
return;
|
|
981
1132
|
}
|
|
982
|
-
if (
|
|
983
|
-
|
|
1133
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:close") {
|
|
1134
|
+
handleRequestClose();
|
|
984
1135
|
return;
|
|
985
1136
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1137
|
+
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:haptic") {
|
|
1138
|
+
performRampkitHaptic(data);
|
|
1139
|
+
return;
|
|
989
1140
|
}
|
|
990
|
-
|
|
1141
|
+
}
|
|
1142
|
+
catch (_e) {
|
|
1143
|
+
// String path
|
|
1144
|
+
if (raw === "rampkit:tap" ||
|
|
1145
|
+
raw === "next" ||
|
|
1146
|
+
raw === "continue") {
|
|
991
1147
|
handleAdvance(i);
|
|
1148
|
+
return;
|
|
992
1149
|
}
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1150
|
+
if (raw === "rampkit:request-review" || raw === "rampkit:review") {
|
|
1151
|
+
(async () => {
|
|
1152
|
+
try {
|
|
1153
|
+
const available = await RampKitNative_1.StoreReview.isAvailableAsync();
|
|
1154
|
+
if (available) {
|
|
1155
|
+
await RampKitNative_1.StoreReview.requestReview();
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
catch (_) { }
|
|
1159
|
+
})();
|
|
1160
|
+
return;
|
|
998
1161
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1162
|
+
if (raw === "rampkit:request-notification-permission") {
|
|
1163
|
+
handleNotificationPermissionRequest(undefined);
|
|
1164
|
+
return;
|
|
1001
1165
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:close") {
|
|
1005
|
-
handleRequestClose();
|
|
1006
|
-
return;
|
|
1007
|
-
}
|
|
1008
|
-
if ((data === null || data === void 0 ? void 0 : data.type) === "rampkit:haptic") {
|
|
1009
|
-
performRampkitHaptic(data);
|
|
1010
|
-
return;
|
|
1011
|
-
}
|
|
1012
|
-
}
|
|
1013
|
-
catch (_e) {
|
|
1014
|
-
// String path
|
|
1015
|
-
if (raw === "rampkit:tap" ||
|
|
1016
|
-
raw === "next" ||
|
|
1017
|
-
raw === "continue") {
|
|
1018
|
-
handleAdvance(i);
|
|
1019
|
-
return;
|
|
1020
|
-
}
|
|
1021
|
-
if (raw === "rampkit:request-review" || raw === "rampkit:review") {
|
|
1022
|
-
(async () => {
|
|
1166
|
+
if (raw === "rampkit:onboarding-finished") {
|
|
1167
|
+
setOnboardingCompleted(true);
|
|
1023
1168
|
try {
|
|
1024
|
-
|
|
1025
|
-
if (available) {
|
|
1026
|
-
await RampKitNative_1.StoreReview.requestReview();
|
|
1027
|
-
}
|
|
1169
|
+
(_c = props.onOnboardingFinished) === null || _c === void 0 ? void 0 : _c.call(props, undefined);
|
|
1028
1170
|
}
|
|
1029
1171
|
catch (_) { }
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
}
|
|
1033
|
-
if (raw === "rampkit:request-notification-permission") {
|
|
1034
|
-
handleNotificationPermissionRequest(undefined);
|
|
1035
|
-
return;
|
|
1036
|
-
}
|
|
1037
|
-
if (raw === "rampkit:onboarding-finished") {
|
|
1038
|
-
setOnboardingCompleted(true);
|
|
1039
|
-
try {
|
|
1040
|
-
(_c = props.onOnboardingFinished) === null || _c === void 0 ? void 0 : _c.call(props, undefined);
|
|
1041
|
-
}
|
|
1042
|
-
catch (_) { }
|
|
1043
|
-
handleRequestClose({ completed: true });
|
|
1044
|
-
return;
|
|
1045
|
-
}
|
|
1046
|
-
if (raw === "rampkit:show-paywall") {
|
|
1047
|
-
try {
|
|
1048
|
-
(_d = props.onShowPaywall) === null || _d === void 0 ? void 0 : _d.call(props);
|
|
1049
|
-
}
|
|
1050
|
-
catch (_) { }
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1053
|
-
if (raw === "rampkit:goBack") {
|
|
1054
|
-
if (i > 0) {
|
|
1055
|
-
navigateToIndex(i - 1);
|
|
1172
|
+
handleRequestClose({ completed: true });
|
|
1173
|
+
return;
|
|
1056
1174
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1175
|
+
if (raw === "rampkit:show-paywall") {
|
|
1176
|
+
try {
|
|
1177
|
+
(_d = props.onShowPaywall) === null || _d === void 0 ? void 0 : _d.call(props);
|
|
1178
|
+
}
|
|
1179
|
+
catch (_) { }
|
|
1180
|
+
return;
|
|
1059
1181
|
}
|
|
1060
|
-
|
|
1061
|
-
}
|
|
1062
|
-
if (raw.startsWith("rampkit:navigate:")) {
|
|
1063
|
-
const target = raw.slice("rampkit:navigate:".length);
|
|
1064
|
-
if (target === "__goBack__") {
|
|
1182
|
+
if (raw === "rampkit:goBack") {
|
|
1065
1183
|
if (i > 0) {
|
|
1066
1184
|
navigateToIndex(i - 1);
|
|
1067
1185
|
}
|
|
@@ -1070,58 +1188,55 @@ function Overlay(props) {
|
|
|
1070
1188
|
}
|
|
1071
1189
|
return;
|
|
1072
1190
|
}
|
|
1073
|
-
if (
|
|
1074
|
-
|
|
1191
|
+
if (raw.startsWith("rampkit:navigate:")) {
|
|
1192
|
+
const target = raw.slice("rampkit:navigate:".length);
|
|
1193
|
+
if (target === "__goBack__") {
|
|
1194
|
+
if (i > 0) {
|
|
1195
|
+
navigateToIndex(i - 1);
|
|
1196
|
+
}
|
|
1197
|
+
else {
|
|
1198
|
+
handleRequestClose();
|
|
1199
|
+
}
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
if (!target || target === "__continue__") {
|
|
1203
|
+
handleAdvance(i);
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
const targetIndex = props.screens.findIndex((s) => s.id === target);
|
|
1207
|
+
if (targetIndex >= 0) {
|
|
1208
|
+
navigateToIndex(targetIndex);
|
|
1209
|
+
}
|
|
1210
|
+
else {
|
|
1211
|
+
handleAdvance(i);
|
|
1212
|
+
}
|
|
1075
1213
|
return;
|
|
1076
1214
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1215
|
+
if (raw === "rampkit:close") {
|
|
1216
|
+
handleRequestClose();
|
|
1217
|
+
return;
|
|
1080
1218
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1219
|
+
if (raw.startsWith("haptic:")) {
|
|
1220
|
+
performRampkitHaptic({
|
|
1221
|
+
type: "rampkit:haptic",
|
|
1222
|
+
nodeId: null,
|
|
1223
|
+
nodeType: null,
|
|
1224
|
+
animation: "none",
|
|
1225
|
+
action: "haptic",
|
|
1226
|
+
hapticType: "impact",
|
|
1227
|
+
impactStyle: "Medium",
|
|
1228
|
+
notificationType: null,
|
|
1229
|
+
timestamp: Date.now(),
|
|
1230
|
+
});
|
|
1231
|
+
return;
|
|
1083
1232
|
}
|
|
1084
|
-
return;
|
|
1085
1233
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
type: "rampkit:haptic",
|
|
1093
|
-
nodeId: null,
|
|
1094
|
-
nodeType: null,
|
|
1095
|
-
animation: "none",
|
|
1096
|
-
action: "haptic",
|
|
1097
|
-
hapticType: "impact",
|
|
1098
|
-
impactStyle: "Medium",
|
|
1099
|
-
notificationType: null,
|
|
1100
|
-
timestamp: Date.now(),
|
|
1101
|
-
});
|
|
1102
|
-
return;
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
// No-op for other messages, but useful to log while testing
|
|
1106
|
-
// console.log("WebView message:", raw);
|
|
1107
|
-
}, onError: (e) => {
|
|
1108
|
-
// You can surface an inline error UI here if you want
|
|
1109
|
-
console.warn("WebView error:", e.nativeEvent);
|
|
1110
|
-
} }) }, props.screens[i].id))) }), slideFadeActive && slideFadeOutgoingIndex !== null && slideFadeIncomingIndex !== null && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { pointerEvents: "none", style: [
|
|
1111
|
-
react_native_1.StyleSheet.absoluteFillObject,
|
|
1112
|
-
styles.slideFadeLayer,
|
|
1113
|
-
{
|
|
1114
|
-
opacity: slideFadeOutgoingOpacity,
|
|
1115
|
-
transform: [{ translateX: slideFadeOutgoingTranslateX }],
|
|
1116
|
-
},
|
|
1117
|
-
], children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { style: styles.webview, originWhitelist: ["*"], source: { html: docs[slideFadeOutgoingIndex] }, 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 }) }), (0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { pointerEvents: "none", style: [
|
|
1118
|
-
react_native_1.StyleSheet.absoluteFillObject,
|
|
1119
|
-
styles.slideFadeLayer,
|
|
1120
|
-
{
|
|
1121
|
-
opacity: slideFadeIncomingOpacity,
|
|
1122
|
-
transform: [{ translateX: slideFadeIncomingTranslateX }],
|
|
1123
|
-
},
|
|
1124
|
-
], children: (0, jsx_runtime_1.jsx)(react_native_webview_1.WebView, { style: styles.webview, originWhitelist: ["*"], source: { html: docs[slideFadeIncomingIndex] }, 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 }) })] })), (0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { pointerEvents: isTransitioning ? "auto" : "none", style: [
|
|
1234
|
+
// No-op for other messages, but useful to log while testing
|
|
1235
|
+
// console.log("WebView message:", raw);
|
|
1236
|
+
}, onError: (e) => {
|
|
1237
|
+
// You can surface an inline error UI here if you want
|
|
1238
|
+
console.warn("WebView error:", e.nativeEvent);
|
|
1239
|
+
} }) }, props.screens[i].id))) }) }), (0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { pointerEvents: isTransitioning ? "auto" : "none", style: [
|
|
1125
1240
|
react_native_1.StyleSheet.absoluteFillObject,
|
|
1126
1241
|
styles.curtain,
|
|
1127
1242
|
{ opacity: fadeOpacity },
|
|
@@ -1144,9 +1259,5 @@ const styles = react_native_1.StyleSheet.create({
|
|
|
1144
1259
|
center: { flex: 1, alignItems: "center", justifyContent: "center" },
|
|
1145
1260
|
webview: { flex: 1 },
|
|
1146
1261
|
curtain: { backgroundColor: "white" },
|
|
1147
|
-
slideFadeLayer: {
|
|
1148
|
-
backgroundColor: "white",
|
|
1149
|
-
zIndex: 10000,
|
|
1150
|
-
},
|
|
1151
1262
|
});
|
|
1152
1263
|
exports.default = Overlay;
|
package/package.json
CHANGED