rampkit-expo-dev 0.0.111 → 0.0.112

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.
@@ -5,12 +5,16 @@ export declare const injectedVarsHandler = "\n(function(){\n try {\n if (win
5
5
  export declare const injectedDynamicTapHandler = "\n(function() {\n if (window.__rampkitClickInterceptorInstalled) return;\n window.__rampkitClickInterceptorInstalled = true;\n\n // Decode HTML entities\n function decodeHtml(str) {\n if (!str) return str;\n return str.replace(/&quot;/g, '\"').replace(/&#34;/g, '\"').replace(/&#x22;/g, '\"')\n .replace(/&apos;/g, \"'\").replace(/&#39;/g, \"'\").replace(/&#x27;/g, \"'\")\n .replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&amp;/g, '&');\n }\n\n // Find dynamic tap config on element or ancestors\n function findDynamicTap(el) {\n var current = el;\n var depth = 0;\n var attrNames = ['data-tap-dynamic', 'data-tapdynamic', 'tapDynamic', 'data-dynamic-tap'];\n while (current && current !== document.body && current !== document.documentElement && depth < 20) {\n if (current.getAttribute) {\n for (var i = 0; i < attrNames.length; i++) {\n var attr = current.getAttribute(attrNames[i]);\n if (attr && attr.length > 2) {\n return { element: current, config: attr };\n }\n }\n if (current.dataset && current.dataset.tapDynamic) {\n return { element: current, config: current.dataset.tapDynamic };\n }\n }\n current = current.parentElement;\n depth++;\n }\n return null;\n }\n \n // Get variables for condition evaluation - check ALL possible sources\n function getVars() {\n var vars = {};\n if (window.__rampkitVariables) {\n Object.keys(window.__rampkitVariables).forEach(function(k) {\n vars[k] = window.__rampkitVariables[k];\n });\n }\n if (window.__rampkitVars) {\n Object.keys(window.__rampkitVars).forEach(function(k) {\n vars[k] = window.__rampkitVars[k];\n });\n }\n if (window.RK_VARS) {\n Object.keys(window.RK_VARS).forEach(function(k) {\n vars[k] = window.RK_VARS[k];\n });\n }\n return vars;\n }\n \n // Evaluate a single rule\n function evalRule(rule, vars) {\n if (!rule || !rule.key) return false;\n var left = vars[rule.key];\n var right = rule.value;\n var op = rule.op || '=';\n if (left === undefined || left === null) left = '';\n if (right === undefined || right === null) right = '';\n var leftStr = String(left);\n var rightStr = String(right);\n var result = false;\n switch (op) {\n case '=': case '==': result = leftStr === rightStr; break;\n case '!=': case '<>': result = leftStr !== rightStr; break;\n case '>': result = parseFloat(left) > parseFloat(right); break;\n case '<': result = parseFloat(left) < parseFloat(right); break;\n case '>=': result = parseFloat(left) >= parseFloat(right); break;\n case '<=': result = parseFloat(left) <= parseFloat(right); break;\n default: result = false;\n }\n return result;\n }\n \n // Evaluate all rules (AND logic)\n function evalRules(rules, vars) {\n if (!rules || !rules.length) return true;\n for (var i = 0; i < rules.length; i++) {\n if (!evalRule(rules[i], vars)) return false;\n }\n return true;\n }\n \n // Execute an action\n function execAction(action) {\n if (!action || !action.type) return;\n var msg = null;\n var actionType = action.type.toLowerCase();\n \n switch (actionType) {\n case 'navigate':\n msg = { type: 'rampkit:navigate', targetScreenId: action.targetScreenId || '__continue__', animation: action.animation || 'fade' };\n break;\n case 'continue':\n msg = { type: 'rampkit:navigate', targetScreenId: '__continue__', animation: action.animation || 'fade' };\n break;\n case 'goback':\n msg = { type: 'rampkit:goBack', animation: action.animation || 'fade' };\n break;\n case 'close':\n msg = { type: 'rampkit:close' };\n break;\n case 'haptic':\n msg = { type: 'rampkit:haptic', hapticType: action.hapticType || 'impact', impactStyle: action.impactStyle || 'Medium', notificationType: action.notificationType };\n break;\n case 'showpaywall':\n msg = { type: 'rampkit:show-paywall', payload: action.payload || { paywallId: action.paywallId } };\n break;\n case 'requestreview':\n msg = { type: 'rampkit:request-review' };\n break;\n case 'requestnotificationpermission':\n msg = { type: 'rampkit:request-notification-permission' };\n break;\n case 'onboardingfinished':\n case 'finishonboarding':\n case 'finish':\n msg = { type: 'rampkit:onboarding-finished', payload: action.payload };\n break;\n case 'setvariable':\n case 'setstate':\n case 'updatevariable':\n case 'set':\n case 'assign':\n var varKey = action.key || action.variableName || action.name || action.variable;\n var varValue = action.variableValue !== undefined ? action.variableValue :\n action.value !== undefined ? action.value :\n action.newValue !== undefined ? action.newValue : undefined;\n if (varKey && varValue !== undefined) {\n if (window.__rampkitVariables) window.__rampkitVariables[varKey] = varValue;\n if (window.__rampkitVars) window.__rampkitVars[varKey] = varValue;\n var updateVars = {};\n updateVars[varKey] = varValue;\n msg = { type: 'rampkit:variables', vars: updateVars };\n }\n break;\n }\n if (msg) {\n try {\n if (window.ReactNativeWebView && window.ReactNativeWebView.postMessage) {\n window.ReactNativeWebView.postMessage(JSON.stringify(msg));\n }\n } catch(e) {}\n }\n }\n \n // Evaluate dynamic tap config\n function evalDynamicTap(config) {\n if (!config || !config.values) return false;\n var vars = getVars();\n var conditions = config.values;\n for (var i = 0; i < conditions.length; i++) {\n var cond = conditions[i];\n var condType = cond.conditionType || 'if';\n var rules = cond.rules || [];\n var actions = cond.actions || [];\n if (condType === 'else' || evalRules(rules, vars)) {\n for (var j = 0; j < actions.length; j++) {\n execAction(actions[j]);\n }\n return true;\n }\n }\n return false;\n }\n \n // Click interceptor - capture phase, runs BEFORE onclick handlers\n function interceptClick(event) {\n var result = findDynamicTap(event.target);\n if (!result) return;\n\n try {\n var configStr = decodeHtml(result.config);\n var config = JSON.parse(configStr);\n var handled = evalDynamicTap(config);\n if (handled) {\n event.stopImmediatePropagation();\n event.preventDefault();\n return false;\n }\n } catch (e) {\n // Dynamic tap error - silent\n }\n }\n\n // Install interceptor on window in capture phase\n window.addEventListener('click', interceptClick, true);\n})();\n";
6
6
  export declare const injectedTemplateResolver = "\n(function() {\n 'use strict';\n if (window.__rampkitTemplatesResolved) return;\n\n var ctx = window.rampkitContext || { device: {}, user: {} };\n var stateVars = window.__rampkitVariables || {};\n\n // Build flat variable map accessible for updates\n window.__rampkitVars = window.__rampkitVars || {};\n var vars = window.__rampkitVars;\n\n // Storage for original templates (enables re-resolution on variable updates)\n var templateStore = [];\n var attrTemplateStore = [];\n\n function rebuildVars() {\n for (var key in vars) {\n if (vars.hasOwnProperty(key)) delete vars[key];\n }\n // Device variables (e.g., device.platform)\n if (ctx.device) {\n Object.keys(ctx.device).forEach(function(key) {\n vars['device.' + key] = ctx.device[key];\n });\n }\n // User variables (e.g., user.id)\n if (ctx.user) {\n Object.keys(ctx.user).forEach(function(key) {\n vars['user.' + key] = ctx.user[key];\n });\n }\n // Custom state variables (e.g., gender, currentWeight)\n Object.keys(stateVars).forEach(function(key) {\n vars[key] = stateVars[key];\n });\n }\n\n rebuildVars();\n\n function resolveValue(value) {\n if (!value) return '';\n value = value.trim();\n // Double-quoted string\n var dq = value.match(/^\"(.*)\"$/);\n if (dq) return dq[1];\n // Single-quoted string\n var sq = value.match(/^'(.*)'$/);\n if (sq) return sq[1];\n // Variable reference\n if (/^[A-Za-z_][A-Za-z0-9_.]*$/.test(value)) {\n var v = vars[value];\n return (v !== undefined && v !== null) ? String(v) : '';\n }\n return value;\n }\n\n function evaluateCondition(cond) {\n if (!cond) return false;\n cond = cond.trim();\n // Equality check: var == \"value\"\n var eq = cond.match(/^([A-Za-z_][A-Za-z0-9_.]*)\\s*==\\s*(.+)$/);\n if (eq) return String(vars[eq[1]] || '') === resolveValue(eq[2]);\n // Inequality check: var != \"value\"\n var neq = cond.match(/^([A-Za-z_][A-Za-z0-9_.]*)\\s*!=\\s*(.+)$/);\n if (neq) return String(vars[neq[1]] || '') !== resolveValue(neq[2]);\n // Truthy check: just the variable name\n if (/^[A-Za-z_][A-Za-z0-9_.]*$/.test(cond)) {\n var v = vars[cond];\n return v !== undefined && v !== null && v !== '' && v !== false && v !== 0;\n }\n return false;\n }\n\n function resolveTemplate(text) {\n if (!text || typeof text !== 'string' || text.indexOf('${') === -1) return text;\n return text.replace(/\\$\\{([^}]+)\\}/g, function(match, expr) {\n if (!expr) return match;\n expr = expr.trim();\n if (!expr) return '';\n // Simple variable substitution\n if (/^[A-Za-z_][A-Za-z0-9_.]*$/.test(expr)) {\n var v = vars[expr];\n if (v === undefined || v === null) return '';\n if (typeof v === 'boolean') return v ? 'true' : 'false';\n return String(v);\n }\n // Ternary expression: condition ? trueValue : falseValue\n var q = expr.indexOf('?'), c = expr.indexOf(':');\n if (q > 0 && c > q) {\n var condition = expr.substring(0, q).trim();\n var rest = expr.substring(q + 1);\n var ci = rest.indexOf(':');\n if (ci > 0) {\n var tv = rest.substring(0, ci).trim();\n var fv = rest.substring(ci + 1).trim();\n return resolveValue(evaluateCondition(condition) ? tv : fv);\n }\n }\n return '';\n });\n }\n\n function resolveAllTemplates() {\n // Walk all text nodes\n var walker = document.createTreeWalker(\n document.body || document.documentElement,\n NodeFilter.SHOW_TEXT, null, false\n );\n var node, nodes = [];\n while (node = walker.nextNode()) {\n if (node.textContent && node.textContent.indexOf('${') !== -1) {\n nodes.push(node);\n }\n }\n nodes.forEach(function(n) {\n var orig = n.textContent;\n var resolved = resolveTemplate(orig);\n if (resolved !== orig) {\n templateStore.push({ node: n, original: orig });\n n.textContent = resolved;\n }\n });\n // Also resolve in common attributes\n var attrs = ['src', 'href', 'alt', 'title', 'placeholder', 'value', 'data-text'];\n document.querySelectorAll('*').forEach(function(el) {\n attrs.forEach(function(a) {\n var v = el.getAttribute(a);\n if (v && v.indexOf('${') !== -1) {\n attrTemplateStore.push({ element: el, attr: a, original: v });\n el.setAttribute(a, resolveTemplate(v));\n }\n });\n });\n }\n\n function reResolveTemplates() {\n // Re-resolve stored text nodes\n templateStore.forEach(function(item) {\n if (item.node && item.node.parentNode) {\n item.node.textContent = resolveTemplate(item.original);\n }\n });\n // Re-resolve stored attributes\n attrTemplateStore.forEach(function(item) {\n if (item.element && item.element.parentNode) {\n item.element.setAttribute(item.attr, resolveTemplate(item.original));\n }\n });\n }\n\n // Listen for variable updates via custom event\n document.addEventListener('rampkit:vars-updated', function(e) {\n if (e.detail) {\n Object.keys(e.detail).forEach(function(k) { stateVars[k] = e.detail[k]; });\n window.__rampkitVariables = stateVars;\n rebuildVars();\n reResolveTemplates();\n }\n });\n\n // Also listen for message events (native broadcasts)\n document.addEventListener('message', function(event) {\n try {\n var data = event.data;\n if (typeof data === 'string') data = JSON.parse(data);\n if (data && data.type === 'rampkit:variables' && data.vars) {\n Object.keys(data.vars).forEach(function(k) { stateVars[k] = data.vars[k]; });\n window.__rampkitVariables = stateVars;\n rebuildVars();\n reResolveTemplates();\n }\n } catch(e) {}\n });\n\n // Run on DOM ready\n if (document.body) {\n resolveAllTemplates();\n } else {\n document.addEventListener('DOMContentLoaded', resolveAllTemplates);\n }\n\n window.__rampkitTemplatesResolved = true;\n\n // Expose for manual re-resolution after dynamic content changes\n window.rampkitResolveTemplates = function() {\n resolveAllTemplates();\n };\n\n // Expose for programmatic variable updates\n window.rampkitUpdateVariables = function(newVars) {\n if (!newVars) return;\n Object.keys(newVars).forEach(function(k) { stateVars[k] = newVars[k]; });\n window.__rampkitVariables = stateVars;\n rebuildVars();\n reResolveTemplates();\n };\n})();\n";
7
7
  export declare const injectedButtonAnimations = "\n(function(){\n try {\n if (window.__rkButtonAnimApplied) return true;\n window.__rkButtonAnimApplied = true;\n\n var pressed = null;\n var pressedOriginalTransform = '';\n var pressedOriginalOpacity = '';\n var pressedOriginalTransition = '';\n var releaseTimer = null;\n\n // Find interactive element - looks for clickable-looking elements\n function findInteractive(el) {\n var current = el;\n for (var i = 0; i < 20 && current && current !== document.body && current !== document.documentElement; i++) {\n if (!current || !current.tagName) { current = current.parentElement; continue; }\n var tag = current.tagName.toLowerCase();\n\n // Skip tiny elements (likely icons inside buttons)\n var rect = current.getBoundingClientRect();\n if (rect.width < 20 || rect.height < 20) { current = current.parentElement; continue; }\n\n // Match standard interactive elements\n if (tag === 'button' || tag === 'a' || tag === 'input' || tag === 'select') return current;\n\n // Match elements with tap/click-related data attributes\n // Exclude lifecycle attributes like data-on-open-actions, data-on-close-actions\n var attrs = current.attributes;\n if (attrs) {\n for (var j = 0; j < attrs.length; j++) {\n var attrName = attrs[j].name.toLowerCase();\n // Skip lifecycle attributes (on-open, on-close, on-load, on-appear, etc.)\n // These are for screen lifecycle events, not user tap interactions\n var isLifecycleAttr = (attrName.indexOf('on-open') !== -1 || attrName.indexOf('on-close') !== -1 ||\n attrName.indexOf('on-load') !== -1 || attrName.indexOf('on-appear') !== -1 ||\n attrName.indexOf('onopen') !== -1 || attrName.indexOf('onclose') !== -1 ||\n attrName.indexOf('onload') !== -1 || attrName.indexOf('onappear') !== -1);\n if (isLifecycleAttr) {\n continue;\n }\n // Match tap/click interaction attributes\n if (attrName.indexOf('click') !== -1 || attrName.indexOf('tap') !== -1 ||\n attrName.indexOf('action') !== -1 || attrName.indexOf('navigate') !== -1 ||\n attrName.indexOf('press') !== -1) {\n return current;\n }\n }\n }\n\n // Match elements with onclick\n if (current.onclick || current.hasAttribute('onclick')) return current;\n\n // Match elements with role=\"button\"\n if (current.getAttribute('role') === 'button') return current;\n\n // Match any element with an ID containing button/btn/cta\n var id = current.id || '';\n if (id && (id.toLowerCase().indexOf('button') !== -1 || id.toLowerCase().indexOf('btn') !== -1 || id.toLowerCase().indexOf('cta') !== -1)) return current;\n\n // Match elements with button-like classes\n var className = current.className;\n if (className && typeof className === 'string') {\n var cls = className.toLowerCase();\n if (cls.indexOf('btn') !== -1 || cls.indexOf('button') !== -1 || cls.indexOf('cta') !== -1 ||\n cls.indexOf('clickable') !== -1 || cls.indexOf('tappable') !== -1 || cls.indexOf('pressable') !== -1) {\n return current;\n }\n }\n\n // Match elements with cursor pointer\n try {\n var computed = window.getComputedStyle(current);\n if (computed && computed.cursor === 'pointer') return current;\n } catch(e) {}\n\n current = current.parentElement;\n }\n return null;\n }\n\n function applyPressedStyle(el) {\n if (!el || !el.style) return;\n // Save original styles\n pressedOriginalTransform = el.style.transform || '';\n pressedOriginalOpacity = el.style.opacity || '';\n pressedOriginalTransition = el.style.transition || '';\n // Apply pressed style with inline styles for maximum specificity\n el.style.transition = 'transform 80ms cubic-bezier(0.25, 0.1, 0.25, 1), opacity 80ms cubic-bezier(0.25, 0.1, 0.25, 1)';\n el.style.transform = 'scale(0.97)';\n el.style.opacity = '0.8';\n }\n\n function applyReleasedStyle(el) {\n if (!el || !el.style) return;\n // Apply spring-back animation\n el.style.transition = 'transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1), opacity 280ms cubic-bezier(0.34, 1.56, 0.64, 1)';\n el.style.transform = pressedOriginalTransform || 'scale(1)';\n el.style.opacity = pressedOriginalOpacity || '1';\n }\n\n function resetStyle(el) {\n if (!el || !el.style) return;\n el.style.transform = pressedOriginalTransform;\n el.style.opacity = pressedOriginalOpacity;\n el.style.transition = pressedOriginalTransition;\n }\n\n function onTouchStart(e) {\n try {\n var target = findInteractive(e.target);\n if (!target) return;\n if (releaseTimer) { clearTimeout(releaseTimer); releaseTimer = null; }\n if (pressed && pressed !== target) { resetStyle(pressed); }\n applyPressedStyle(target);\n pressed = target;\n } catch(err) {}\n }\n \n function onTouchEnd(e) {\n try {\n if (!pressed) return;\n var t = pressed;\n applyReleasedStyle(t);\n releaseTimer = setTimeout(function() {\n resetStyle(t);\n releaseTimer = null;\n }, 300);\n pressed = null;\n } catch(err) {}\n }\n \n function onTouchCancel(e) {\n try {\n if (!pressed) return;\n resetStyle(pressed);\n pressed = null;\n if (releaseTimer) { clearTimeout(releaseTimer); releaseTimer = null; }\n } catch(err) {}\n }\n \n // Use capture phase for immediate response before any other handlers\n document.addEventListener('touchstart', onTouchStart, { passive: true, capture: true });\n document.addEventListener('touchend', onTouchEnd, { passive: true, capture: true });\n document.addEventListener('touchcancel', onTouchCancel, { passive: true, capture: true });\n // Mouse events for testing\n document.addEventListener('mousedown', onTouchStart, { passive: true, capture: true });\n document.addEventListener('mouseup', onTouchEnd, { passive: true, capture: true });\n \n } catch (err) {}\n true;\n})();\n";
8
+ export declare const injectedTranslationScript = "\n(function() {\n var RTL_LANGUAGES = ['ar', 'he', 'fa', 'ur'];\n\n function applyTranslations(translations, locale, language) {\n if (!translations || typeof translations !== 'object') return;\n\n // Fallback chain: exact locale -> language code -> nothing\n var t = translations[locale] || translations[language] || null;\n if (!t) return;\n\n // Apply RTL if needed\n if (RTL_LANGUAGES.indexOf(language) !== -1) {\n document.documentElement.setAttribute('dir', 'rtl');\n document.documentElement.setAttribute('lang', language);\n }\n\n // Replace text content by data-ramp-id\n Object.keys(t).forEach(function(id) {\n var el = document.querySelector('[data-ramp-id=\"' + id + '\"]');\n if (el) {\n el.textContent = t[id];\n }\n });\n }\n\n // Expose for immediate call\n window.__rampkitApplyTranslations = applyTranslations;\n})();\n";
8
9
  export type ScreenPayload = {
9
10
  id: string;
10
11
  label?: string;
11
12
  html: string;
12
13
  css?: string;
13
14
  js?: string;
15
+ /** Optional translations keyed by language/locale code (e.g., "es", "ar", "es_MX")
16
+ * Each translation is a dictionary mapping data-ramp-id to translated text */
17
+ translations?: Record<string, Record<string, string>>;
14
18
  };
15
19
  export declare function showRampkitOverlay(opts: {
16
20
  onboardingId: 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.injectedButtonAnimations = exports.injectedTemplateResolver = exports.injectedDynamicTapHandler = exports.injectedVarsHandler = exports.injectedNoSelect = exports.injectedHardening = void 0;
39
+ exports.injectedTranslationScript = exports.injectedButtonAnimations = exports.injectedTemplateResolver = exports.injectedDynamicTapHandler = exports.injectedVarsHandler = exports.injectedNoSelect = exports.injectedHardening = void 0;
40
40
  exports.showRampkitOverlay = showRampkitOverlay;
41
41
  exports.hideRampkitOverlay = hideRampkitOverlay;
42
42
  exports.closeRampkitOverlay = closeRampkitOverlay;
@@ -753,6 +753,39 @@ exports.injectedButtonAnimations = `
753
753
  true;
754
754
  })();
755
755
  `;
756
+ // Translation script for localized content
757
+ // Replaces text content in elements with data-ramp-id attributes
758
+ // Supports RTL languages (Arabic, Hebrew, Persian, Urdu)
759
+ exports.injectedTranslationScript = `
760
+ (function() {
761
+ var RTL_LANGUAGES = ['ar', 'he', 'fa', 'ur'];
762
+
763
+ function applyTranslations(translations, locale, language) {
764
+ if (!translations || typeof translations !== 'object') return;
765
+
766
+ // Fallback chain: exact locale -> language code -> nothing
767
+ var t = translations[locale] || translations[language] || null;
768
+ if (!t) return;
769
+
770
+ // Apply RTL if needed
771
+ if (RTL_LANGUAGES.indexOf(language) !== -1) {
772
+ document.documentElement.setAttribute('dir', 'rtl');
773
+ document.documentElement.setAttribute('lang', language);
774
+ }
775
+
776
+ // Replace text content by data-ramp-id
777
+ Object.keys(t).forEach(function(id) {
778
+ var el = document.querySelector('[data-ramp-id="' + id + '"]');
779
+ if (el) {
780
+ el.textContent = t[id];
781
+ }
782
+ });
783
+ }
784
+
785
+ // Expose for immediate call
786
+ window.__rampkitApplyTranslations = applyTranslations;
787
+ })();
788
+ `;
756
789
  function performRampkitHaptic(event) {
757
790
  if (!event) {
758
791
  // Backwards compatible default
@@ -1199,8 +1232,17 @@ function buildHtmlDocument(screen, variables, requiredScripts, rampkitContext) {
1199
1232
  // Convert literal \n escape sequences to actual newlines
1200
1233
  // CSS white-space: pre-line will render them as line breaks
1201
1234
  html = html.replace(/\\n/g, '\n');
1235
+ // Translation support
1236
+ const locale = context.device.locale;
1237
+ const language = context.device.language;
1238
+ const rtlLanguages = ['ar', 'he', 'fa', 'ur'];
1239
+ const isRTL = rtlLanguages.includes(language);
1240
+ const translations = screen.translations;
1241
+ const translationCall = translations
1242
+ ? `window.__rampkitApplyTranslations(${JSON.stringify(translations)}, "${locale}", "${language}");`
1243
+ : '';
1202
1244
  return `<!doctype html>
1203
- <html>
1245
+ <html${isRTL ? ' dir="rtl"' : ''} lang="${language}">
1204
1246
  <head>
1205
1247
  <meta charset="utf-8"/>
1206
1248
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover"/>
@@ -1216,6 +1258,9 @@ ${html}
1216
1258
  window.rampkitContext = ${JSON.stringify(context)};
1217
1259
  // State variables from onboarding
1218
1260
  window.__rampkitVariables = ${JSON.stringify(variables || {})};
1261
+ // Translation support
1262
+ ${exports.injectedTranslationScript}
1263
+ ${translationCall}
1219
1264
  ${js}
1220
1265
  </script>
1221
1266
  </body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.111",
3
+ "version": "0.0.112",
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",