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.
@@ -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;
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.40",
3
+ "version": "0.0.41",
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",