@duffel/react-native-components-assistant 0.4.3 → 0.4.5-canary.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.
@@ -1,11 +1,21 @@
1
1
  "use strict";
2
2
 
3
3
  import React from 'react';
4
- import { Modal, Platform, StyleSheet, View } from 'react-native';
4
+ import { Linking, Modal, Platform, StyleSheet, View } from 'react-native';
5
5
  import { WebView } from 'react-native-webview';
6
6
  import { hasJsonWebTokenFormat } from "./lib/hasJsonWebTokenFormat.js";
7
7
  import { getClientKeyPayload } from "./lib/getClientKeyPayload.js";
8
8
  import { jsx as _jsx } from "react/jsx-runtime";
9
+ const assistantIframeUrl = 'https://assets.duffel.com/assistant/iframe.html';
10
+ const isHttpUrl = url => /^https?:\/\//.test(url);
11
+ const isAssistantIframeUrl = url => {
12
+ try {
13
+ const parsedUrl = new URL(url);
14
+ return `${parsedUrl.origin}${parsedUrl.pathname}` === assistantIframeUrl;
15
+ } catch (error) {
16
+ return false;
17
+ }
18
+ };
9
19
  export const DuffelAssistant = ({
10
20
  isOpen,
11
21
  onClose,
@@ -19,7 +29,7 @@ export const DuffelAssistant = ({
19
29
  if (!clientKeyPayload) {
20
30
  throw new Error('The client key property is invalid. A client key must follow the JWT format.');
21
31
  }
22
- const clientKeyIncludesResource = clientKeyPayload.order_id !== undefined || clientKeyPayload.booking_id !== undefined;
32
+ const clientKeyIncludesResource = clientKeyPayload.order_id !== undefined || clientKeyPayload.booking_id !== undefined || clientKeyPayload.cars_booking_id !== undefined;
23
33
  if (!('user_id' in clientKeyPayload)) {
24
34
  throw new Error('The client key in the props does not include a user_id. Make sure a user_id is included in the payload of the client key creation.');
25
35
  }
@@ -36,6 +46,35 @@ export const DuffelAssistant = ({
36
46
  if (properties.showMinimiseButton && typeof properties.onMinimise !== 'function') {
37
47
  console.warn('The showMinimiseButton prop is set to true, but the onMinimise callback is not provided. Make sure to listen to the onMinimise callback to handle the minimisation of the Assistant.');
38
48
  }
49
+ const handleMessage = event => {
50
+ if (event.nativeEvent.data === 'duffel-assistant-close') {
51
+ onClose();
52
+ }
53
+ if (typeof properties.onMinimise === 'function' && event.nativeEvent.data === 'duffel-assistant-minimise') {
54
+ properties.onMinimise();
55
+ }
56
+ try {
57
+ const parsedData = JSON.parse(event.nativeEvent.data);
58
+ if (parsedData.type === 'duffel-assistant-new-message' && typeof parsedData.userId === 'string' && typeof parsedData.resourceId === 'string' && typeof onNewMessage === 'function') {
59
+ onNewMessage({
60
+ userId: parsedData.userId,
61
+ resourceId: parsedData.resourceId
62
+ });
63
+ }
64
+ } catch (error) {
65
+ // do nothing, invalid JSON
66
+ }
67
+ };
68
+ const handleShouldStartLoadWithRequest = request => {
69
+ if (!isHttpUrl(request.url) || isAssistantIframeUrl(request.url)) {
70
+ return true;
71
+ }
72
+ if (Platform.OS === 'ios' && request.navigationType !== 'click') {
73
+ return true;
74
+ }
75
+ Linking.openURL(request.url).catch(() => {});
76
+ return false;
77
+ };
39
78
  return /*#__PURE__*/_jsx(Modal, {
40
79
  visible: isOpen,
41
80
  onRequestClose: () => onClose(),
@@ -50,27 +89,10 @@ export const DuffelAssistant = ({
50
89
  // If that's not possible, you can also upload the assistant built assets to a different folder in assets.duffel and work with that.
51
90
  ,
52
91
  source: {
53
- uri: 'https://assets.duffel.com/assistant/iframe.html'
92
+ uri: assistantIframeUrl
54
93
  },
55
- onMessage: event => {
56
- if (event.nativeEvent.data === 'duffel-assistant-close') {
57
- onClose();
58
- }
59
- if (typeof properties.onMinimise === 'function' && event.nativeEvent.data === 'duffel-assistant-minimise') {
60
- properties.onMinimise();
61
- }
62
- try {
63
- const parsedData = JSON.parse(event.nativeEvent.data);
64
- if (parsedData.type === 'duffel-assistant-new-message' && typeof parsedData.userId === 'string' && typeof parsedData.resourceId === 'string' && typeof onNewMessage === 'function') {
65
- onNewMessage({
66
- userId: parsedData.userId,
67
- resourceId: parsedData.resourceId
68
- });
69
- }
70
- } catch (error) {
71
- // do nothing, invalid JSON
72
- }
73
- }
94
+ onMessage: handleMessage,
95
+ onShouldStartLoadWithRequest: handleShouldStartLoadWithRequest
74
96
  }) : /*#__PURE__*/_jsx(WebView
75
97
  // Required for Android
76
98
  , {
@@ -84,13 +106,10 @@ export const DuffelAssistant = ({
84
106
  );
85
107
  true;`,
86
108
  source: {
87
- uri: 'https://assets.duffel.com/assistant/iframe.html'
109
+ uri: assistantIframeUrl
88
110
  },
89
- onMessage: event => {
90
- if (event.nativeEvent.data === 'duffel-assistant-close') {
91
- onClose();
92
- }
93
- }
111
+ onMessage: handleMessage,
112
+ onShouldStartLoadWithRequest: handleShouldStartLoadWithRequest
94
113
  })
95
114
  })
96
115
  });
@@ -1 +1 @@
1
- {"version":3,"names":["React","Modal","Platform","StyleSheet","View","WebView","hasJsonWebTokenFormat","getClientKeyPayload","jsx","_jsx","DuffelAssistant","isOpen","onClose","onNewMessage","properties","clientKey","Error","clientKeyPayload","clientKeyIncludesResource","order_id","undefined","booking_id","issueType","console","warn","context","showMinimiseButton","onMinimise","visible","onRequestClose","animationType","children","style","styles","container","OS","injectedJavaScriptObject","source","uri","onMessage","event","nativeEvent","data","parsedData","JSON","parse","type","userId","resourceId","error","injectedJavaScript","stringify","create","height","width","paddingHorizontal","paddingTop","paddingBottom"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","Linking","Modal","Platform","StyleSheet","View","WebView","hasJsonWebTokenFormat","getClientKeyPayload","jsx","_jsx","assistantIframeUrl","isHttpUrl","url","test","isAssistantIframeUrl","parsedUrl","URL","origin","pathname","error","DuffelAssistant","isOpen","onClose","onNewMessage","properties","clientKey","Error","clientKeyPayload","clientKeyIncludesResource","order_id","undefined","booking_id","cars_booking_id","issueType","console","warn","context","showMinimiseButton","onMinimise","handleMessage","event","nativeEvent","data","parsedData","JSON","parse","type","userId","resourceId","handleShouldStartLoadWithRequest","request","OS","navigationType","openURL","catch","visible","onRequestClose","animationType","children","style","styles","container","injectedJavaScriptObject","source","uri","onMessage","onShouldStartLoadWithRequest","injectedJavaScript","stringify","create","height","width","paddingHorizontal","paddingTop","paddingBottom"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -29,6 +29,9 @@ export function getClientKeyPayload(clientKey) {
29
29
  }),
30
30
  ...(json.booking_id && {
31
31
  booking_id: json.booking_id
32
+ }),
33
+ ...(json.cars_booking_id && {
34
+ cars_booking_id: json.cars_booking_id
32
35
  })
33
36
  };
34
37
  return data;
@@ -1 +1 @@
1
- {"version":3,"names":["getClientKeyPayload","clientKey","payload","split","Error","decodedPayload","atob","json","JSON","parse","data","exp","user_id","live_mode","organisation_id","order_id","booking_id","error"],"sourceRoot":"../../../src","sources":["lib/getClientKeyPayload.ts"],"mappings":";;AAgCA,OAAO,SAASA,mBAAmBA,CACjCC,SAAiB,EACQ;EACzB,IAAI,OAAOA,SAAS,KAAK,QAAQ,EAAE;IACjC,OAAO,IAAI;EACb;EAEA,MAAMC,OAAO,GAAGD,SAAS,CAACE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;EACvC,IAAI,CAACD,OAAO,EAAE;IACZ,MAAM,IAAIE,KAAK,CACb,uFACF,CAAC;EACH;EAEA,IAAI;IACF,MAAMC,cAAc,GAAGC,IAAI,CAACJ,OAAO,CAAC;IAEpC,MAAMK,IAAI,GAAGC,IAAI,CAACC,KAAK,CAACJ,cAAc,CAAC;IACvC,MAAMK,IAAI,GAAG;MACX,IAAIH,IAAI,CAACI,GAAG,IAAI;QAAEA,GAAG,EAAEJ,IAAI,CAACI;MAAI,CAAC,CAAC;MAClC,IAAIJ,IAAI,CAACK,OAAO,IAAI;QAAEA,OAAO,EAAEL,IAAI,CAACK;MAAQ,CAAC,CAAC;MAC9C,IAAIL,IAAI,CAACM,SAAS,IAAI;QAAEA,SAAS,EAAEN,IAAI,CAACM;MAAU,CAAC,CAAC;MACpD,IAAIN,IAAI,CAACO,eAAe,IAAI;QAC1BA,eAAe,EAAEP,IAAI,CAACO;MACxB,CAAC,CAAC;MACF,IAAIP,IAAI,CAACQ,QAAQ,IAAI;QAAEA,QAAQ,EAAER,IAAI,CAACQ;MAAS,CAAC,CAAC;MACjD,IAAIR,IAAI,CAACS,UAAU,IAAI;QAAEA,UAAU,EAAET,IAAI,CAACS;MAAW,CAAC;IACxD,CAAC;IACD,OAAON,IAAI;EACb,CAAC,CAAC,OAAOO,KAAK,EAAE;IACd,OAAO,IAAI;EACb;AACF","ignoreList":[]}
1
+ {"version":3,"names":["getClientKeyPayload","clientKey","payload","split","Error","decodedPayload","atob","json","JSON","parse","data","exp","user_id","live_mode","organisation_id","order_id","booking_id","cars_booking_id","error"],"sourceRoot":"../../../src","sources":["lib/getClientKeyPayload.ts"],"mappings":";;AAqCA,OAAO,SAASA,mBAAmBA,CACjCC,SAAiB,EACQ;EACzB,IAAI,OAAOA,SAAS,KAAK,QAAQ,EAAE;IACjC,OAAO,IAAI;EACb;EAEA,MAAMC,OAAO,GAAGD,SAAS,CAACE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;EACvC,IAAI,CAACD,OAAO,EAAE;IACZ,MAAM,IAAIE,KAAK,CACb,uFACF,CAAC;EACH;EAEA,IAAI;IACF,MAAMC,cAAc,GAAGC,IAAI,CAACJ,OAAO,CAAC;IAEpC,MAAMK,IAAI,GAAGC,IAAI,CAACC,KAAK,CAACJ,cAAc,CAAC;IACvC,MAAMK,IAAI,GAAG;MACX,IAAIH,IAAI,CAACI,GAAG,IAAI;QAAEA,GAAG,EAAEJ,IAAI,CAACI;MAAI,CAAC,CAAC;MAClC,IAAIJ,IAAI,CAACK,OAAO,IAAI;QAAEA,OAAO,EAAEL,IAAI,CAACK;MAAQ,CAAC,CAAC;MAC9C,IAAIL,IAAI,CAACM,SAAS,IAAI;QAAEA,SAAS,EAAEN,IAAI,CAACM;MAAU,CAAC,CAAC;MACpD,IAAIN,IAAI,CAACO,eAAe,IAAI;QAC1BA,eAAe,EAAEP,IAAI,CAACO;MACxB,CAAC,CAAC;MACF,IAAIP,IAAI,CAACQ,QAAQ,IAAI;QAAEA,QAAQ,EAAER,IAAI,CAACQ;MAAS,CAAC,CAAC;MACjD,IAAIR,IAAI,CAACS,UAAU,IAAI;QAAEA,UAAU,EAAET,IAAI,CAACS;MAAW,CAAC,CAAC;MACvD,IAAIT,IAAI,CAACU,eAAe,IAAI;QAAEA,eAAe,EAAEV,IAAI,CAACU;MAAgB,CAAC;IACvE,CAAC;IACD,OAAOP,IAAI;EACb,CAAC,CAAC,OAAOQ,KAAK,EAAE;IACd,OAAO,IAAI;EACb;AACF","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,oBAAoB,IAAI,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAInG,MAAM,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;AAEhE,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+H1D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,EAAE,KAAK,oBAAoB,IAAI,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAInG,MAAM,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;AA2BhE,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAgJ1D,CAAC"}
@@ -23,6 +23,10 @@ export type ClientKeyPayload = {
23
23
  * The ID of a booking when integrating the chat only mode.
24
24
  */
25
25
  booking_id?: string;
26
+ /**
27
+ * The ID of a cars booking when integrating the chat only mode.
28
+ */
29
+ cars_booking_id?: string;
26
30
  };
27
31
  export declare function getClientKeyPayload(clientKey: string): ClientKeyPayload | null;
28
32
  //# sourceMappingURL=getClientKeyPayload.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getClientKeyPayload.d.ts","sourceRoot":"","sources":["../../../../src/lib/getClientKeyPayload.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CA8BzB"}
1
+ {"version":3,"file":"getClientKeyPayload.d.ts","sourceRoot":"","sources":["../../../../src/lib/getClientKeyPayload.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,GAChB,gBAAgB,GAAG,IAAI,CA+BzB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duffel/react-native-components-assistant",
3
- "version": "0.4.3",
3
+ "version": "0.4.5-canary.0",
4
4
  "description": "Duffel Assistant component in React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -59,29 +59,29 @@
59
59
  "registry": "https://registry.npmjs.org/"
60
60
  },
61
61
  "devDependencies": {
62
- "@commitlint/config-conventional": "^19.6.0",
63
- "@eslint/compat": "^1.2.7",
64
- "@eslint/eslintrc": "^3.3.0",
65
- "@eslint/js": "^9.22.0",
66
- "@evilmartians/lefthook": "^1.5.0",
62
+ "@commitlint/config-conventional": "20.4.4",
63
+ "@eslint/compat": "1.2.7",
64
+ "@eslint/eslintrc": "3.3.0",
65
+ "@eslint/js": "9.22.0",
66
+ "@evilmartians/lefthook": "1.5.0",
67
67
  "@react-native/babel-preset": "0.78.2",
68
- "@react-native/eslint-config": "^0.78.0",
69
- "@release-it/conventional-changelog": "^9.0.2",
70
- "@types/jest": "^29.5.5",
71
- "@types/react": "^19.0.12",
72
- "commitlint": "^19.6.1",
73
- "del-cli": "^5.1.0",
74
- "eslint": "^9.22.0",
75
- "eslint-config-prettier": "^10.1.1",
76
- "eslint-plugin-prettier": "^5.2.3",
77
- "jest": "^29.7.0",
78
- "prettier": "^3.0.3",
68
+ "@react-native/eslint-config": "0.78.0",
69
+ "@release-it/conventional-changelog": "10.0.6",
70
+ "@types/jest": "29.5.5",
71
+ "@types/react": "19.0.12",
72
+ "commitlint": "20.4.4",
73
+ "del-cli": "5.1.0",
74
+ "eslint": "9.22.0",
75
+ "eslint-config-prettier": "10.1.1",
76
+ "eslint-plugin-prettier": "5.2.3",
77
+ "jest": "29.7.0",
78
+ "prettier": "3.0.3",
79
79
  "react": "19.1.0",
80
80
  "react-native": "0.81.5",
81
81
  "react-native-builder-bob": "0.39.0",
82
82
  "react-native-webview": "13.15.0",
83
- "release-it": "^19.2.2",
84
- "typescript": "^5.8.3"
83
+ "release-it": "19.2.4",
84
+ "typescript": "5.8.3"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "react": "*",
@@ -154,6 +154,6 @@
154
154
  "version": "0.51.1"
155
155
  },
156
156
  "dependencies": {
157
- "expo": "^54.0.30"
157
+ "expo": "54.0.30"
158
158
  }
159
159
  }
package/src/index.tsx CHANGED
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { Modal, Platform, StyleSheet, View } from 'react-native';
2
+ import { Linking, Modal, Platform, StyleSheet, View } from 'react-native';
3
3
  import { WebView } from 'react-native-webview';
4
4
  import { type DuffelAssistantProps as DuffelAssistantPropsImported } from './DuffelAssistantProps';
5
5
  import { hasJsonWebTokenFormat } from './lib/hasJsonWebTokenFormat';
@@ -7,6 +7,31 @@ import { getClientKeyPayload } from './lib/getClientKeyPayload';
7
7
 
8
8
  export type DuffelAssistantProps = DuffelAssistantPropsImported;
9
9
 
10
+ const assistantIframeUrl = 'https://assets.duffel.com/assistant/iframe.html';
11
+
12
+ type WebViewMessageEvent = {
13
+ nativeEvent: {
14
+ data: string;
15
+ };
16
+ };
17
+
18
+ type ShouldStartLoadRequest = {
19
+ navigationType?: string;
20
+ url: string;
21
+ };
22
+
23
+ const isHttpUrl = (url: string) => /^https?:\/\//.test(url);
24
+
25
+ const isAssistantIframeUrl = (url: string) => {
26
+ try {
27
+ const parsedUrl = new URL(url);
28
+
29
+ return `${parsedUrl.origin}${parsedUrl.pathname}` === assistantIframeUrl;
30
+ } catch (error) {
31
+ return false;
32
+ }
33
+ };
34
+
10
35
  export const DuffelAssistant: React.FC<DuffelAssistantProps> = ({
11
36
  isOpen,
12
37
  onClose,
@@ -26,7 +51,8 @@ export const DuffelAssistant: React.FC<DuffelAssistantProps> = ({
26
51
 
27
52
  const clientKeyIncludesResource =
28
53
  clientKeyPayload.order_id !== undefined ||
29
- clientKeyPayload.booking_id !== undefined;
54
+ clientKeyPayload.booking_id !== undefined ||
55
+ clientKeyPayload.cars_booking_id !== undefined;
30
56
 
31
57
  if (!('user_id' in clientKeyPayload)) {
32
58
  throw new Error(
@@ -65,6 +91,53 @@ export const DuffelAssistant: React.FC<DuffelAssistantProps> = ({
65
91
  );
66
92
  }
67
93
 
94
+ const handleMessage = (event: WebViewMessageEvent) => {
95
+ if (event.nativeEvent.data === 'duffel-assistant-close') {
96
+ onClose();
97
+ }
98
+
99
+ if (
100
+ typeof properties.onMinimise === 'function' &&
101
+ event.nativeEvent.data === 'duffel-assistant-minimise'
102
+ ) {
103
+ properties.onMinimise();
104
+ }
105
+
106
+ try {
107
+ const parsedData = JSON.parse(event.nativeEvent.data);
108
+
109
+ if (
110
+ parsedData.type === 'duffel-assistant-new-message' &&
111
+ typeof parsedData.userId === 'string' &&
112
+ typeof parsedData.resourceId === 'string' &&
113
+ typeof onNewMessage === 'function'
114
+ ) {
115
+ onNewMessage({
116
+ userId: parsedData.userId,
117
+ resourceId: parsedData.resourceId,
118
+ });
119
+ }
120
+ } catch (error) {
121
+ // do nothing, invalid JSON
122
+ }
123
+ };
124
+
125
+ const handleShouldStartLoadWithRequest = (
126
+ request: ShouldStartLoadRequest
127
+ ) => {
128
+ if (!isHttpUrl(request.url) || isAssistantIframeUrl(request.url)) {
129
+ return true;
130
+ }
131
+
132
+ if (Platform.OS === 'ios' && request.navigationType !== 'click') {
133
+ return true;
134
+ }
135
+
136
+ Linking.openURL(request.url).catch(() => {});
137
+
138
+ return false;
139
+ };
140
+
68
141
  return (
69
142
  <Modal
70
143
  visible={isOpen}
@@ -79,37 +152,9 @@ export const DuffelAssistant: React.FC<DuffelAssistantProps> = ({
79
152
  // If you try ngrok with the local esbuild server it will fail because ngrok requests in https and the dev server rejects http requests.
80
153
  // Easiest solution is to use the production URL with test data.
81
154
  // If that's not possible, you can also upload the assistant built assets to a different folder in assets.duffel and work with that.
82
- source={{ uri: 'https://assets.duffel.com/assistant/iframe.html' }}
83
- onMessage={(event) => {
84
- if (event.nativeEvent.data === 'duffel-assistant-close') {
85
- onClose();
86
- }
87
-
88
- if (
89
- typeof properties.onMinimise === 'function' &&
90
- event.nativeEvent.data === 'duffel-assistant-minimise'
91
- ) {
92
- properties.onMinimise();
93
- }
94
-
95
- try {
96
- const parsedData = JSON.parse(event.nativeEvent.data);
97
-
98
- if (
99
- parsedData.type === 'duffel-assistant-new-message' &&
100
- typeof parsedData.userId === 'string' &&
101
- typeof parsedData.resourceId === 'string' &&
102
- typeof onNewMessage === 'function'
103
- ) {
104
- onNewMessage({
105
- userId: parsedData.userId,
106
- resourceId: parsedData.resourceId,
107
- });
108
- }
109
- } catch (error) {
110
- // do nothing, invalid JSON
111
- }
112
- }}
155
+ source={{ uri: assistantIframeUrl }}
156
+ onMessage={handleMessage}
157
+ onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
113
158
  />
114
159
  ) : (
115
160
  <WebView
@@ -123,12 +168,9 @@ export const DuffelAssistant: React.FC<DuffelAssistantProps> = ({
123
168
  "*",
124
169
  );
125
170
  true;`}
126
- source={{ uri: 'https://assets.duffel.com/assistant/iframe.html' }}
127
- onMessage={(event) => {
128
- if (event.nativeEvent.data === 'duffel-assistant-close') {
129
- onClose();
130
- }
131
- }}
171
+ source={{ uri: assistantIframeUrl }}
172
+ onMessage={handleMessage}
173
+ onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
132
174
  />
133
175
  )}
134
176
  </View>
@@ -28,6 +28,11 @@ export type ClientKeyPayload = {
28
28
  * The ID of a booking when integrating the chat only mode.
29
29
  */
30
30
  booking_id?: string;
31
+
32
+ /**
33
+ * The ID of a cars booking when integrating the chat only mode.
34
+ */
35
+ cars_booking_id?: string;
31
36
  };
32
37
 
33
38
  export function getClientKeyPayload(
@@ -57,6 +62,7 @@ export function getClientKeyPayload(
57
62
  }),
58
63
  ...(json.order_id && { order_id: json.order_id }),
59
64
  ...(json.booking_id && { booking_id: json.booking_id }),
65
+ ...(json.cars_booking_id && { cars_booking_id: json.cars_booking_id }),
60
66
  };
61
67
  return data as ClientKeyPayload;
62
68
  } catch (error) {