rampkit-expo-dev 0.0.40 → 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 +144 -3
- 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) {
|
|
@@ -827,7 +968,7 @@ function Overlay(props) {
|
|
|
827
968
|
opacity: pagerOpacity,
|
|
828
969
|
transform: [{ translateX: pagerTranslateX }],
|
|
829
970
|
},
|
|
830
|
-
], 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: () => {
|
|
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: () => {
|
|
831
972
|
setLoadedCount((c) => c + 1);
|
|
832
973
|
if (i === 0) {
|
|
833
974
|
setFirstPageLoaded(true);
|
package/package.json
CHANGED