@savers_app/react-native-sandbox-sdk 1.3.0 → 1.4.0

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.
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=react-native-svg.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["@types/react-native-svg.d.ts"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ import React from 'react';
4
+ import { Path, Svg } from 'react-native-svg';
5
+
6
+ /** Matches `m.saversapp.com/assets/svg/BackIcon.tsx` (17×16). */
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const DEFAULT_COLOR = '#66CC99';
9
+ export const TravelPortalBackIcon = ({
10
+ height = 16,
11
+ width = 17,
12
+ color = DEFAULT_COLOR
13
+ }) => /*#__PURE__*/_jsx(Svg, {
14
+ width: width,
15
+ height: height,
16
+ viewBox: "0 0 17 16",
17
+ fill: "none",
18
+ children: /*#__PURE__*/_jsx(Path, {
19
+ d: "M.293 7.293a1 1 0 000 1.414l6.364 6.364a1 1 0 001.414-1.414L2.414 8l5.657-5.657A1 1 0 006.657.93L.293 7.293zM1 9h16V7H1v2z",
20
+ fill: color
21
+ })
22
+ });
23
+ export default TravelPortalBackIcon;
24
+ //# sourceMappingURL=TravelPortalBackIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","Path","Svg","jsx","_jsx","DEFAULT_COLOR","TravelPortalBackIcon","height","width","color","viewBox","fill","children","d"],"sourceRoot":"../../../src","sources":["components/TravelPortalBackIcon.tsx"],"mappings":";;AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,IAAI,EAAEC,GAAG,QAAQ,kBAAkB;;AAE5C;AAAA,SAAAC,GAAA,IAAAC,IAAA;AAOA,MAAMC,aAAa,GAAG,SAAS;AAE/B,OAAO,MAAMC,oBAAyD,GAAGA,CAAC;EACxEC,MAAM,GAAG,EAAE;EACXC,KAAK,GAAG,EAAE;EACVC,KAAK,GAAGJ;AACV,CAAC,kBACCD,IAAA,CAACF,GAAG;EAACM,KAAK,EAAEA,KAAM;EAACD,MAAM,EAAEA,MAAO;EAACG,OAAO,EAAC,WAAW;EAACC,IAAI,EAAC,MAAM;EAAAC,QAAA,eAChER,IAAA,CAACH,IAAI;IACHY,CAAC,EAAC,4HAA4H;IAC9HF,IAAI,EAAEF;EAAM,CACb;AAAC,CACC,CACN;AAED,eAAeH,oBAAoB","ignoreList":[]}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ import React, { useEffect, useState } from 'react';
4
+ import { Image, StyleSheet, TouchableOpacity, View } from 'react-native';
5
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
+ import { TravelPortalBackIcon } from "./TravelPortalBackIcon.js";
7
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
+ /** Horizontal padding: Tailwind `px-3.5` in m.saversapp Header. */
9
+ const HEADER_PADDING_X = 14;
10
+ /** Vertical padding: Tailwind `py-4` in m.saversapp Header. */
11
+ const HEADER_PADDING_Y = 16;
12
+ /** Row min height: Tailwind `min-h-[60px]` in m.saversapp Header. */
13
+ const HEADER_ROW_MIN_HEIGHT = 60;
14
+ const LOGO_MAX_WIDTH = 160;
15
+ const LOGO_MAX_HEIGHT = 70;
16
+ const LOGO_MIN_HEIGHT = 40;
17
+ export const TravelPortalHeader = ({
18
+ onBack,
19
+ partnerLogo,
20
+ backIconColor,
21
+ renderBackIcon,
22
+ topInset = 'none',
23
+ style
24
+ }) => {
25
+ const insets = useSafeAreaInsets();
26
+ const paddingTop = topInset === 'safe-area' ? insets.top + HEADER_PADDING_Y : HEADER_PADDING_Y;
27
+ const [logoWidth, setLogoWidth] = useState(LOGO_MAX_WIDTH);
28
+ const [logoHeight, setLogoHeight] = useState(LOGO_MAX_HEIGHT);
29
+ useEffect(() => {
30
+ if (!partnerLogo) {
31
+ return;
32
+ }
33
+ Image.getSize(partnerLogo, (srcWidth, srcHeight) => {
34
+ setLogoWidth(srcWidth > LOGO_MAX_WIDTH ? LOGO_MAX_WIDTH : srcWidth);
35
+ setLogoHeight(srcHeight > LOGO_MAX_HEIGHT ? LOGO_MAX_HEIGHT : srcHeight);
36
+ }, () => {
37
+ setLogoWidth(LOGO_MAX_WIDTH);
38
+ setLogoHeight(LOGO_MAX_HEIGHT);
39
+ });
40
+ }, [partnerLogo]);
41
+ return /*#__PURE__*/_jsx(View, {
42
+ style: [styles.container, {
43
+ paddingTop,
44
+ paddingBottom: HEADER_PADDING_Y
45
+ }, style],
46
+ children: /*#__PURE__*/_jsxs(View, {
47
+ style: styles.row,
48
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
49
+ onPress: onBack,
50
+ hitSlop: 16,
51
+ accessibilityRole: "button",
52
+ accessibilityLabel: "Back",
53
+ style: styles.backButton,
54
+ children: renderBackIcon ? renderBackIcon() : /*#__PURE__*/_jsx(TravelPortalBackIcon, {
55
+ color: backIconColor
56
+ })
57
+ }), partnerLogo ? /*#__PURE__*/_jsx(Image, {
58
+ source: {
59
+ uri: partnerLogo
60
+ },
61
+ resizeMode: "contain",
62
+ style: [styles.logo, {
63
+ width: logoWidth,
64
+ height: logoHeight
65
+ }]
66
+ }) : /*#__PURE__*/_jsx(View, {
67
+ style: styles.logoPlaceholder
68
+ })]
69
+ })
70
+ });
71
+ };
72
+ const styles = StyleSheet.create({
73
+ container: {
74
+ backgroundColor: '#fff',
75
+ paddingHorizontal: HEADER_PADDING_X
76
+ },
77
+ row: {
78
+ flexDirection: 'row',
79
+ alignItems: 'center',
80
+ justifyContent: 'space-between',
81
+ minHeight: HEADER_ROW_MIN_HEIGHT
82
+ },
83
+ backButton: {
84
+ paddingVertical: 8,
85
+ justifyContent: 'center'
86
+ },
87
+ logo: {
88
+ minHeight: LOGO_MIN_HEIGHT,
89
+ alignSelf: 'flex-end'
90
+ },
91
+ logoPlaceholder: {
92
+ width: LOGO_MAX_WIDTH,
93
+ minHeight: LOGO_MIN_HEIGHT
94
+ }
95
+ });
96
+ export default TravelPortalHeader;
97
+ //# sourceMappingURL=TravelPortalHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useEffect","useState","Image","StyleSheet","TouchableOpacity","View","useSafeAreaInsets","TravelPortalBackIcon","jsx","_jsx","jsxs","_jsxs","HEADER_PADDING_X","HEADER_PADDING_Y","HEADER_ROW_MIN_HEIGHT","LOGO_MAX_WIDTH","LOGO_MAX_HEIGHT","LOGO_MIN_HEIGHT","TravelPortalHeader","onBack","partnerLogo","backIconColor","renderBackIcon","topInset","style","insets","paddingTop","top","logoWidth","setLogoWidth","logoHeight","setLogoHeight","getSize","srcWidth","srcHeight","styles","container","paddingBottom","children","row","onPress","hitSlop","accessibilityRole","accessibilityLabel","backButton","color","source","uri","resizeMode","logo","width","height","logoPlaceholder","create","backgroundColor","paddingHorizontal","flexDirection","alignItems","justifyContent","minHeight","paddingVertical","alignSelf"],"sourceRoot":"../../../src","sources":["components/TravelPortalHeader.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
 
3
3
  import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
- import { Image, StyleSheet, TouchableOpacity, View } from 'react-native';
4
+ import { StyleSheet, View } from 'react-native';
5
5
  import WebView from 'react-native-webview';
6
+ import { TravelPortalHeader } from "../../components/TravelPortalHeader.js";
6
7
  import { parseDualWebViewEnvelope } from "./dualWebViewBridge.types.js";
7
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
9
  const DEFAULT_TRAVEL_PORTAL_URL = 'https://sandbox.travelercashback.com';
@@ -45,6 +46,8 @@ export const DualWebViewBridgeController = ({
45
46
  saversAppUrl,
46
47
  travelPortalUrl = DEFAULT_TRAVEL_PORTAL_URL,
47
48
  partnerLogo,
49
+ travelBackIconColor,
50
+ travelHeaderTopInset = 'none',
48
51
  renderTravelBackIcon,
49
52
  initialSurface = 'savers',
50
53
  onSaversSdkMessage,
@@ -184,33 +187,12 @@ export const DualWebViewBridgeController = ({
184
187
  webviewDebuggingEnabled: __DEV__
185
188
  }, saversKey) : null, surface === 'travel' ? /*#__PURE__*/_jsxs(View, {
186
189
  style: styles.travelColumn,
187
- children: [/*#__PURE__*/_jsxs(View, {
188
- style: styles.header,
189
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
190
- onPress: backToSavers,
191
- hitSlop: 16,
192
- accessibilityRole: "button",
193
- accessibilityLabel: "Back",
194
- style: styles.backButton,
195
- children: renderTravelBackIcon ? renderTravelBackIcon() : /*#__PURE__*/_jsxs(View, {
196
- style: styles.backIconWrapper,
197
- children: [/*#__PURE__*/_jsx(View, {
198
- style: styles.backIconShaft
199
- }), /*#__PURE__*/_jsx(View, {
200
- style: styles.backIconHead
201
- })]
202
- })
203
- }), /*#__PURE__*/_jsx(View, {
204
- style: styles.headerSpacer
205
- }), partnerLogo ? /*#__PURE__*/_jsx(Image, {
206
- source: {
207
- uri: partnerLogo
208
- },
209
- resizeMode: "contain",
210
- style: styles.logo
211
- }) : /*#__PURE__*/_jsx(View, {
212
- style: styles.logoPlaceholder
213
- })]
190
+ children: [/*#__PURE__*/_jsx(TravelPortalHeader, {
191
+ onBack: backToSavers,
192
+ partnerLogo: partnerLogo,
193
+ backIconColor: travelBackIconColor,
194
+ topInset: travelHeaderTopInset,
195
+ renderBackIcon: renderTravelBackIcon
214
196
  }), /*#__PURE__*/_jsx(WebView, {
215
197
  ref: travelRef,
216
198
  source: travelSource,
@@ -235,58 +217,6 @@ const styles = StyleSheet.create({
235
217
  },
236
218
  webview: {
237
219
  flex: 1
238
- },
239
- header: {
240
- flexDirection: 'row',
241
- alignItems: 'center',
242
- backgroundColor: '#fff',
243
- paddingHorizontal: 16,
244
- paddingTop: 12,
245
- paddingBottom: 12,
246
- borderBottomWidth: StyleSheet.hairlineWidth,
247
- borderBottomColor: '#E5E5E5'
248
- },
249
- backButton: {
250
- width: 32,
251
- height: 32,
252
- justifyContent: 'center',
253
- alignItems: 'center'
254
- },
255
- backIconWrapper: {
256
- width: 20,
257
- height: 16,
258
- justifyContent: 'center',
259
- position: 'relative'
260
- },
261
- backIconShaft: {
262
- position: 'absolute',
263
- left: 6,
264
- right: 0,
265
- height: 2,
266
- backgroundColor: '#111827',
267
- borderRadius: 1
268
- },
269
- backIconHead: {
270
- width: 10,
271
- height: 10,
272
- borderLeftWidth: 2,
273
- borderBottomWidth: 2,
274
- borderColor: '#111827',
275
- transform: [{
276
- rotate: '45deg'
277
- }],
278
- marginLeft: 1
279
- },
280
- headerSpacer: {
281
- flex: 1
282
- },
283
- logo: {
284
- width: 120,
285
- height: 32
286
- },
287
- logoPlaceholder: {
288
- width: 120,
289
- height: 32
290
220
  }
291
221
  });
292
222
  export default DualWebViewBridgeController;
@@ -1 +1 @@
1
- {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","Image","StyleSheet","TouchableOpacity","View","WebView","parseDualWebViewEnvelope","jsx","_jsx","jsxs","_jsxs","DEFAULT_TRAVEL_PORTAL_URL","WEBVIEW_UA_MARKER","TRAVEL_DEEP_LINK","LEGACY_OPEN_TRAVEL_ACTIONS","resolveTravelPortalUrlFromPayload","payload","trim","url","undefined","resolveTravelPortalUrlFromLegacyMessage","data","topLevel","buildInjectNativeBridgeScript","detail","JSON","stringify","DualWebViewBridgeController","saversAppUrl","travelPortalUrl","partnerLogo","renderTravelBackIcon","initialSurface","onSaversSdkMessage","onLoadEndSavers","onLoadEndTravel","saversRef","travelRef","surface","setSurface","saversKey","setSaversKey","travelKey","setTravelKey","activeTravelPortalUrl","setActiveTravelPortalUrl","openTravel","k","backToSavers","relayTo","target","from","bridge","action","ref","current","injectJavaScript","handleBridgeEnvelope","env","to","tryLegacyOpenTravel","raw","parse","type","some","s","includes","onMessageSavers","e","nativeEvent","postBack","onMessageTravel","onShouldStartLoadSavers","request","startsWith","travelSource","uri","saversSource","style","styles","root","children","source","originWhitelist","applicationNameForUserAgent","onMessage","onShouldStartLoadWithRequest","onLoadEnd","webview","sharedCookiesEnabled","incognito","webviewDebuggingEnabled","__DEV__","travelColumn","header","onPress","hitSlop","accessibilityRole","accessibilityLabel","backButton","backIconWrapper","backIconShaft","backIconHead","headerSpacer","resizeMode","logo","logoPlaceholder","create","flex","flexDirection","alignItems","backgroundColor","paddingHorizontal","paddingTop","paddingBottom","borderBottomWidth","hairlineWidth","borderBottomColor","width","height","justifyContent","position","left","right","borderRadius","borderLeftWidth","borderColor","transform","rotate","marginLeft"],"sourceRoot":"../../../../src","sources":["services/webview/DualWebViewBridgeController.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","StyleSheet","View","WebView","TravelPortalHeader","parseDualWebViewEnvelope","jsx","_jsx","jsxs","_jsxs","DEFAULT_TRAVEL_PORTAL_URL","WEBVIEW_UA_MARKER","TRAVEL_DEEP_LINK","LEGACY_OPEN_TRAVEL_ACTIONS","resolveTravelPortalUrlFromPayload","payload","trim","url","undefined","resolveTravelPortalUrlFromLegacyMessage","data","topLevel","buildInjectNativeBridgeScript","detail","JSON","stringify","DualWebViewBridgeController","saversAppUrl","travelPortalUrl","partnerLogo","travelBackIconColor","travelHeaderTopInset","renderTravelBackIcon","initialSurface","onSaversSdkMessage","onLoadEndSavers","onLoadEndTravel","saversRef","travelRef","surface","setSurface","saversKey","setSaversKey","travelKey","setTravelKey","activeTravelPortalUrl","setActiveTravelPortalUrl","openTravel","k","backToSavers","relayTo","target","from","bridge","action","ref","current","injectJavaScript","handleBridgeEnvelope","env","to","tryLegacyOpenTravel","raw","parse","type","some","s","includes","onMessageSavers","e","nativeEvent","postBack","onMessageTravel","onShouldStartLoadSavers","request","startsWith","travelSource","uri","saversSource","style","styles","root","children","source","originWhitelist","applicationNameForUserAgent","onMessage","onShouldStartLoadWithRequest","onLoadEnd","webview","sharedCookiesEnabled","incognito","webviewDebuggingEnabled","__DEV__","travelColumn","onBack","backIconColor","topInset","renderBackIcon","create","flex"],"sourceRoot":"../../../../src","sources":["services/webview/DualWebViewBridgeController.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ /** Matches `m.saversapp.com/assets/svg/BackIcon.tsx` (17×16). */
3
+ export type TravelPortalBackIconProps = {
4
+ height?: number;
5
+ width?: number;
6
+ color?: string;
7
+ };
8
+ export declare const TravelPortalBackIcon: React.FC<TravelPortalBackIconProps>;
9
+ export default TravelPortalBackIcon;
10
+ //# sourceMappingURL=TravelPortalBackIcon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TravelPortalBackIcon.d.ts","sourceRoot":"","sources":["../../../../src/components/TravelPortalBackIcon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,iEAAiE;AACjE,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAIF,eAAO,MAAM,oBAAoB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAWpE,CAAC;AAEF,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { type StyleProp, type ViewStyle } from 'react-native';
3
+ export type TravelPortalHeaderInsets = 'none' | 'safe-area';
4
+ export type TravelPortalHeaderProps = {
5
+ onBack: () => void;
6
+ partnerLogo?: string;
7
+ backIconColor?: string;
8
+ renderBackIcon?: () => React.ReactNode;
9
+ /**
10
+ * `none` — matches m.saversapp `Header` (`py-4` only). Use when the host
11
+ * already reserves top space (e.g. clo-app `MainBodyComponent` hosting bar).
12
+ * `safe-area` — adds device top inset (standalone / full-screen hosts).
13
+ */
14
+ topInset?: TravelPortalHeaderInsets;
15
+ style?: StyleProp<ViewStyle>;
16
+ };
17
+ export declare const TravelPortalHeader: React.FC<TravelPortalHeaderProps>;
18
+ export default TravelPortalHeader;
19
+ //# sourceMappingURL=TravelPortalHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TravelPortalHeader.d.ts","sourceRoot":"","sources":["../../../../src/components/TravelPortalHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AACnD,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,WAAW,CAAC;AAY5D,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CA6EhE,CAAC;AA2BF,eAAe,kBAAkB,CAAC"}
@@ -4,6 +4,10 @@ export type DualWebViewBridgeControllerProps = {
4
4
  saversAppUrl: string;
5
5
  travelPortalUrl?: string;
6
6
  partnerLogo?: string;
7
+ /** Matches m.saversapp `theme.colors.quaternary` (default `#66CC99`). */
8
+ travelBackIconColor?: string;
9
+ /** @default 'none' — host apps like clo-app already reserve top space when hosting. */
10
+ travelHeaderTopInset?: 'none' | 'safe-area';
7
11
  renderTravelBackIcon?: () => React.ReactNode;
8
12
  initialSurface?: Surface;
9
13
  onSaversSdkMessage?: (raw: string, postBack: (data: unknown) => void) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"DualWebViewBridgeController.d.ts","sourceRoot":"","sources":["../../../../../src/services/webview/DualWebViewBridgeController.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4D,MAAM,OAAO,CAAC;AAsCjF,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1C,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAcF,eAAO,MAAM,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAChD,gCAAgC,CA6OjC,CAAC;AA0DF,eAAe,2BAA2B,CAAC"}
1
+ {"version":3,"file":"DualWebViewBridgeController.d.ts","sourceRoot":"","sources":["../../../../../src/services/webview/DualWebViewBridgeController.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AA2Cf,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1C,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,uFAAuF;IACvF,oBAAoB,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAcF,eAAO,MAAM,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAChD,gCAAgC,CAwNjC,CAAC;AAQF,eAAe,2BAA2B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savers_app/react-native-sandbox-sdk",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Cross-platform React Native SDK exposing native features (maps, dial pad, browser), device ID/location and session utilities, a URL generator, and a WebView message bridge to trigger actions from web content.",
5
5
  "main": "./lib/module/index.js",
6
6
  "react-native": "./src/index.tsx",
@@ -94,6 +94,7 @@
94
94
  "react-native": "0.81.5",
95
95
  "react-native-builder-bob": "^0.40.13",
96
96
  "react-native-safe-area-context": "^5.5.2",
97
+ "react-native-svg": "^15.15.1",
97
98
  "react-native-webview": "^13.16.0",
98
99
  "release-it": "^19.0.4",
99
100
  "typescript": "^5.9.2"
@@ -108,6 +109,7 @@
108
109
  "react-native-aes-gcm-crypto": "*",
109
110
  "react-native-device-info": "*",
110
111
  "react-native-safe-area-context": "*",
112
+ "react-native-svg": "*",
111
113
  "react-native-webview": "*"
112
114
  },
113
115
  "workspaces": [
@@ -0,0 +1,19 @@
1
+ declare module 'react-native-svg' {
2
+ import type * as React from 'react';
3
+ import type { ViewProps } from 'react-native';
4
+
5
+ export interface SvgProps extends ViewProps {
6
+ width?: number | string;
7
+ height?: number | string;
8
+ viewBox?: string;
9
+ fill?: string;
10
+ }
11
+
12
+ export interface PathProps {
13
+ d?: string;
14
+ fill?: string;
15
+ }
16
+
17
+ export const Svg: React.FC<SvgProps>;
18
+ export const Path: React.FC<PathProps>;
19
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { Path, Svg } from 'react-native-svg';
3
+
4
+ /** Matches `m.saversapp.com/assets/svg/BackIcon.tsx` (17×16). */
5
+ export type TravelPortalBackIconProps = {
6
+ height?: number;
7
+ width?: number;
8
+ color?: string;
9
+ };
10
+
11
+ const DEFAULT_COLOR = '#66CC99';
12
+
13
+ export const TravelPortalBackIcon: React.FC<TravelPortalBackIconProps> = ({
14
+ height = 16,
15
+ width = 17,
16
+ color = DEFAULT_COLOR,
17
+ }) => (
18
+ <Svg width={width} height={height} viewBox="0 0 17 16" fill="none">
19
+ <Path
20
+ d="M.293 7.293a1 1 0 000 1.414l6.364 6.364a1 1 0 001.414-1.414L2.414 8l5.657-5.657A1 1 0 006.657.93L.293 7.293zM1 9h16V7H1v2z"
21
+ fill={color}
22
+ />
23
+ </Svg>
24
+ );
25
+
26
+ export default TravelPortalBackIcon;
@@ -0,0 +1,143 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import {
3
+ Image,
4
+ StyleSheet,
5
+ TouchableOpacity,
6
+ View,
7
+ type StyleProp,
8
+ type ViewStyle,
9
+ } from 'react-native';
10
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
11
+ import { TravelPortalBackIcon } from './TravelPortalBackIcon';
12
+
13
+ export type TravelPortalHeaderInsets = 'none' | 'safe-area';
14
+
15
+ /** Horizontal padding: Tailwind `px-3.5` in m.saversapp Header. */
16
+ const HEADER_PADDING_X = 14;
17
+ /** Vertical padding: Tailwind `py-4` in m.saversapp Header. */
18
+ const HEADER_PADDING_Y = 16;
19
+ /** Row min height: Tailwind `min-h-[60px]` in m.saversapp Header. */
20
+ const HEADER_ROW_MIN_HEIGHT = 60;
21
+ const LOGO_MAX_WIDTH = 160;
22
+ const LOGO_MAX_HEIGHT = 70;
23
+ const LOGO_MIN_HEIGHT = 40;
24
+
25
+ export type TravelPortalHeaderProps = {
26
+ onBack: () => void;
27
+ partnerLogo?: string;
28
+ backIconColor?: string;
29
+ renderBackIcon?: () => React.ReactNode;
30
+ /**
31
+ * `none` — matches m.saversapp `Header` (`py-4` only). Use when the host
32
+ * already reserves top space (e.g. clo-app `MainBodyComponent` hosting bar).
33
+ * `safe-area` — adds device top inset (standalone / full-screen hosts).
34
+ */
35
+ topInset?: TravelPortalHeaderInsets;
36
+ style?: StyleProp<ViewStyle>;
37
+ };
38
+
39
+ export const TravelPortalHeader: React.FC<TravelPortalHeaderProps> = ({
40
+ onBack,
41
+ partnerLogo,
42
+ backIconColor,
43
+ renderBackIcon,
44
+ topInset = 'none',
45
+ style,
46
+ }) => {
47
+ const insets = useSafeAreaInsets();
48
+ const paddingTop =
49
+ topInset === 'safe-area' ? insets.top + HEADER_PADDING_Y : HEADER_PADDING_Y;
50
+ const [logoWidth, setLogoWidth] = useState(LOGO_MAX_WIDTH);
51
+ const [logoHeight, setLogoHeight] = useState(LOGO_MAX_HEIGHT);
52
+
53
+ useEffect(() => {
54
+ if (!partnerLogo) {
55
+ return;
56
+ }
57
+ Image.getSize(
58
+ partnerLogo,
59
+ (srcWidth, srcHeight) => {
60
+ setLogoWidth(srcWidth > LOGO_MAX_WIDTH ? LOGO_MAX_WIDTH : srcWidth);
61
+ setLogoHeight(
62
+ srcHeight > LOGO_MAX_HEIGHT ? LOGO_MAX_HEIGHT : srcHeight
63
+ );
64
+ },
65
+ () => {
66
+ setLogoWidth(LOGO_MAX_WIDTH);
67
+ setLogoHeight(LOGO_MAX_HEIGHT);
68
+ }
69
+ );
70
+ }, [partnerLogo]);
71
+
72
+ return (
73
+ <View
74
+ style={[
75
+ styles.container,
76
+ {
77
+ paddingTop,
78
+ paddingBottom: HEADER_PADDING_Y,
79
+ },
80
+ style,
81
+ ]}
82
+ >
83
+ <View style={styles.row}>
84
+ <TouchableOpacity
85
+ onPress={onBack}
86
+ hitSlop={16}
87
+ accessibilityRole="button"
88
+ accessibilityLabel="Back"
89
+ style={styles.backButton}
90
+ >
91
+ {renderBackIcon ? (
92
+ renderBackIcon()
93
+ ) : (
94
+ <TravelPortalBackIcon color={backIconColor} />
95
+ )}
96
+ </TouchableOpacity>
97
+
98
+ {partnerLogo ? (
99
+ <Image
100
+ source={{ uri: partnerLogo }}
101
+ resizeMode="contain"
102
+ style={[
103
+ styles.logo,
104
+ {
105
+ width: logoWidth,
106
+ height: logoHeight,
107
+ },
108
+ ]}
109
+ />
110
+ ) : (
111
+ <View style={styles.logoPlaceholder} />
112
+ )}
113
+ </View>
114
+ </View>
115
+ );
116
+ };
117
+
118
+ const styles = StyleSheet.create({
119
+ container: {
120
+ backgroundColor: '#fff',
121
+ paddingHorizontal: HEADER_PADDING_X,
122
+ },
123
+ row: {
124
+ flexDirection: 'row',
125
+ alignItems: 'center',
126
+ justifyContent: 'space-between',
127
+ minHeight: HEADER_ROW_MIN_HEIGHT,
128
+ },
129
+ backButton: {
130
+ paddingVertical: 8,
131
+ justifyContent: 'center',
132
+ },
133
+ logo: {
134
+ minHeight: LOGO_MIN_HEIGHT,
135
+ alignSelf: 'flex-end',
136
+ },
137
+ logoPlaceholder: {
138
+ width: LOGO_MAX_WIDTH,
139
+ minHeight: LOGO_MIN_HEIGHT,
140
+ },
141
+ });
142
+
143
+ export default TravelPortalHeader;
@@ -1,6 +1,13 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
- import { Image, StyleSheet, TouchableOpacity, View } from 'react-native';
1
+ import React, {
2
+ useCallback,
3
+ useEffect,
4
+ useMemo,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
8
+ import { StyleSheet, View } from 'react-native';
3
9
  import WebView from 'react-native-webview';
10
+ import { TravelPortalHeader } from '../../components/TravelPortalHeader';
4
11
  import {
5
12
  type DualWebViewBridgeEnvelope,
6
13
  parseDualWebViewEnvelope,
@@ -15,7 +22,9 @@ const WEBVIEW_UA_MARKER = 'CloAppWebView';
15
22
  const TRAVEL_DEEP_LINK = 'saversapp://travel';
16
23
  const LEGACY_OPEN_TRAVEL_ACTIONS = ['OPEN_TRAVEL_PORTAL', 'OPEN_TRAVEL'];
17
24
 
18
- function resolveTravelPortalUrlFromPayload(payload: unknown): string | undefined {
25
+ function resolveTravelPortalUrlFromPayload(
26
+ payload: unknown
27
+ ): string | undefined {
19
28
  if (typeof payload === 'string' && payload.trim()) {
20
29
  return payload.trim();
21
30
  }
@@ -28,7 +37,9 @@ function resolveTravelPortalUrlFromPayload(payload: unknown): string | undefined
28
37
  return undefined;
29
38
  }
30
39
 
31
- function resolveTravelPortalUrlFromLegacyMessage(data: Record<string, unknown>): string | undefined {
40
+ function resolveTravelPortalUrlFromLegacyMessage(
41
+ data: Record<string, unknown>
42
+ ): string | undefined {
32
43
  const topLevel = data?.url;
33
44
  if (typeof topLevel === 'string' && topLevel.trim()) {
34
45
  return topLevel.trim();
@@ -42,6 +53,10 @@ export type DualWebViewBridgeControllerProps = {
42
53
  saversAppUrl: string;
43
54
  travelPortalUrl?: string;
44
55
  partnerLogo?: string;
56
+ /** Matches m.saversapp `theme.colors.quaternary` (default `#66CC99`). */
57
+ travelBackIconColor?: string;
58
+ /** @default 'none' — host apps like clo-app already reserve top space when hosting. */
59
+ travelHeaderTopInset?: 'none' | 'safe-area';
45
60
  renderTravelBackIcon?: () => React.ReactNode;
46
61
  initialSurface?: Surface;
47
62
  onSaversSdkMessage?: (raw: string, postBack: (data: unknown) => void) => void;
@@ -67,6 +82,8 @@ export const DualWebViewBridgeController: React.FC<
67
82
  saversAppUrl,
68
83
  travelPortalUrl = DEFAULT_TRAVEL_PORTAL_URL,
69
84
  partnerLogo,
85
+ travelBackIconColor,
86
+ travelHeaderTopInset = 'none',
70
87
  renderTravelBackIcon,
71
88
  initialSurface = 'savers',
72
89
  onSaversSdkMessage,
@@ -252,36 +269,13 @@ export const DualWebViewBridgeController: React.FC<
252
269
 
253
270
  {surface === 'travel' ? (
254
271
  <View style={styles.travelColumn}>
255
- <View style={styles.header}>
256
- <TouchableOpacity
257
- onPress={backToSavers}
258
- hitSlop={16}
259
- accessibilityRole="button"
260
- accessibilityLabel="Back"
261
- style={styles.backButton}
262
- >
263
- {renderTravelBackIcon ? (
264
- renderTravelBackIcon()
265
- ) : (
266
- <View style={styles.backIconWrapper}>
267
- <View style={styles.backIconShaft} />
268
- <View style={styles.backIconHead} />
269
- </View>
270
- )}
271
- </TouchableOpacity>
272
-
273
- <View style={styles.headerSpacer} />
274
-
275
- {partnerLogo ? (
276
- <Image
277
- source={{ uri: partnerLogo }}
278
- resizeMode="contain"
279
- style={styles.logo}
280
- />
281
- ) : (
282
- <View style={styles.logoPlaceholder} />
283
- )}
284
- </View>
272
+ <TravelPortalHeader
273
+ onBack={backToSavers}
274
+ partnerLogo={partnerLogo}
275
+ backIconColor={travelBackIconColor}
276
+ topInset={travelHeaderTopInset}
277
+ renderBackIcon={renderTravelBackIcon}
278
+ />
285
279
  <WebView
286
280
  key={travelKey}
287
281
  ref={travelRef}
@@ -305,56 +299,6 @@ const styles = StyleSheet.create({
305
299
  root: { flex: 1 },
306
300
  travelColumn: { flex: 1 },
307
301
  webview: { flex: 1 },
308
- header: {
309
- flexDirection: 'row',
310
- alignItems: 'center',
311
- backgroundColor: '#fff',
312
- paddingHorizontal: 16,
313
- paddingTop: 12,
314
- paddingBottom: 12,
315
- borderBottomWidth: StyleSheet.hairlineWidth,
316
- borderBottomColor: '#E5E5E5',
317
- },
318
- backButton: {
319
- width: 32,
320
- height: 32,
321
- justifyContent: 'center',
322
- alignItems: 'center',
323
- },
324
- backIconWrapper: {
325
- width: 20,
326
- height: 16,
327
- justifyContent: 'center',
328
- position: 'relative',
329
- },
330
- backIconShaft: {
331
- position: 'absolute',
332
- left: 6,
333
- right: 0,
334
- height: 2,
335
- backgroundColor: '#111827',
336
- borderRadius: 1,
337
- },
338
- backIconHead: {
339
- width: 10,
340
- height: 10,
341
- borderLeftWidth: 2,
342
- borderBottomWidth: 2,
343
- borderColor: '#111827',
344
- transform: [{ rotate: '45deg' }],
345
- marginLeft: 1,
346
- },
347
- headerSpacer: {
348
- flex: 1,
349
- },
350
- logo: {
351
- width: 120,
352
- height: 32,
353
- },
354
- logoPlaceholder: {
355
- width: 120,
356
- height: 32,
357
- },
358
302
  });
359
303
 
360
304
  export default DualWebViewBridgeController;